I am writing a Spring Boot REST API using JPA, so I have my application layers consisting of
- controllers
- services
- repositories
- entities
- models for request, response, DTOs
This question is mainly around entities which often have relationships among themselves.
For example, a @OneToMany
relationship to map to database tables with a 1:M relationship.
This is all clear but in the case when we have a case or related entities like for example a Car can have many Parts. Here, by related, I mean that if I POST a Car, I also want to POST all it's Parts. Similarly, if I GET a Car, I also want to GET all of its Parts.
In this case, our Car entity would have @OneToMany
like:
@Entity(name = "car")
public class CarEntity {
...
@Id @GeneratedValue(...)
private Long id;
@OneToMany(mappedBy = "carDetails", cascade = CascadeType.ALL)
private List<PartEntity> parts;
}
and Part entity would have @ManyToOne
like:
@Entity(name = "part")
public class PartEntity {
...
@ManyToOne
@JoinColumn(name = "car_id")
private CarEntity carDetails;
}
To persist a Car, we would have to provide a JSON payload holding data for both Car and its Parts in the payload in order to save both Car and Parts:
{
"vendor": "Toyota",
"model": "Camry"
"parts": [
{
"gasket": "A103",
"price": "16"
},
{
"tire": "Good year",
"price": "149"
}
]
}
,this would persist both Car and its Parts to repository.
Same when issuing GET request, retrieving a Car would also retrieve its Parts.
This is all clear.
However, we might have a 1:M relation where data in M is kind of unrelated to data in 1 side of relationship.
For example let's say we are logging events for say audit purposes. Each Event is logged in EVENT table. But we also want to forward this event to some downstream API, so we also log if the Event was sent to this downstream API in EVENT_LOG table.
So, we have EVENT : EVENT_LOG 1:M relationship where one EVENT can have multiple EVENT_LOGs. In this case, EVENT_LOG is *related logically but it is unrelated for business logic" as it just represents data for logging / auditing purposes.
This means also that EVENT_LOG data should not be part of JSON payload for POST or GET requests.
Let's say we have these table definitions:
EVENT[ID (PK), NAME]
EVENT_LOG[ID (PK), EVENT_ID (FK), SENT]
above, PKs are handled by the database, and SENT field is defaulted to 0 for not sent and updated to 1 if sent. For example:
EVENT [1, 'save_data_event', 2022-10-12T15:17:001]
EVENT_LOG [1, 1, 0, 2022-10-12T15:17:002] // 0 = default (not sent)
Here, we would like to send JSON payload containing only EVENT data:
{
"vendor": "some_data_event"
}
This would populate EVENT table like above. However, using the above @OneToMany
relationship in Entity classes, it would not populate data in EVENT_LOG which is not what we want. We want them both populated.
Similarly for POST requests, we want only relevant data from EVENT table as EVENT_LOG data is not of interest and it should not be included in JSON GET payload.
The way to solve this that come to my mind would be:
- make separate call in code to insert EVENT, then insert EVENT_LOG (not efficient)
- make a call to a stored procedure to insert both at once (EVENT and EVENT_LOG)
My question is can and how can this be achieved by use of Entity annotations like @OneToMany
rather than 1 or 2 above so that when saving an EVENT, also EVENT_LOG is saved but when retrieving an EVENT, no EVENT_LOG is retrieved?
EVENT_LOG
to be saved onEVENT
saving, but when retrieving anEVENT
- you don't want to loadEVENT_LOG
from the db, am I right?