0

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:

  1. make separate call in code to insert EVENT, then insert EVENT_LOG (not efficient)
  2. 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?

5
  • Why would a car to part be a 1 to many? My Camry shares parts with Caldinas and Corollas. I should think this is a many to many relationship.
    – kiwiron
    Aug 12, 2022 at 6:29
  • You get the point, it is an example, assume it is 1:M. Not a question about car industry.
    – dbnex14
    Aug 12, 2022 at 15:44
  • If I understand you'd like an EVENT_LOG to be saved on EVENT saving, but when retrieving an EVENT - you don't want to load EVENT_LOG from the db, am I right? Aug 23, 2022 at 17:57
  • Yes, that is correct
    – dbnex14
    Aug 23, 2022 at 21:31
  • @yezper Thanks to yezper's answer here stackoverflow.com/questions/73510987/…
    – dbnex14
    Aug 30, 2022 at 23:10

1 Answer 1

0

@yezper Thanks to yezper's answer here https://stackoverflow.com/questions/73510987/spring-jpa-hibernate-foreign-key-is-never-set

@Entity
@Table(name = "EVENT")
public class EventEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "ID")
    private Long id;

    @OneToMany(mappedBy = "event", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<EventLogEntity> eventLogs;
    
    ...
}


@Entity
@Table(name = "EVENT_LOG")
public class EventLogEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "EVENT_ID")
    private EventEntity event;

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.