[java] What is “the inverse side of the association” in a bidirectional JPA OneToMany/ManyToOne association?

Table relationships vs. entity relationships

In a relational database system, there can be only three types of table relationships:

  • one-to-many (via a Foreign Key column)
  • one-to-one (via a shared Primary Key)
  • many-to-many (via a link table with two Foreign Keys referencing two separate parent tables)

So, a one-to-many table relationship looks as follows:

one-to-many table relationship

Note that the relationship is based on the Foreign Key column (e.g., post_id) in the child table.

So, there is a single source of truth when it comes to managing a one-to-many table relationship.

Now, if you take a bidirectional entity relationship that maps on the one-to-many table relationship we saw previously:

Bidirectional One-To-Many entity association

If you take a look at the diagram above, you can see that there are two ways to manage this relationship.

In the Post entity, you have the comments collection:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

And, in the PostComment, the post association is mapped as follows:

@ManyToOne(
    fetch = FetchType.LAZY
)
@JoinColumn(name = "post_id")
private Post post;

So, you have two sides that can change the entity association:

  • By adding an entry in the comments child collection, a new post_comment row should be associated with the parent post entity via its post_id column.
  • By setting the post property of the PostComment entity, the post_id column should be updated as well.

Because there are two ways to represent the Foreign Key column, you must define which is the source of truth when it comes to translating the association state change into its equivalent Foreign Key column value modification.

MappedBy (a.k.a the inverse side)

The mappedBy attribute tells that the @ManyToOne side is in charge of managing the Foreign Key column, and the collection is used only to fetch the child entities and to cascade parent entity state changes to children (e.g., removing the parent should also remove the child entities).

It's called the inverse side because it references the child entity property that manages this table relationship.

Synchronize both sides of a bidirectional association

Now, even if you defined the mappedBy attribute and the child-side @ManyToOne association manages the Foreign Key column, you still need to synchronize both sides of the bidirectional association.

The best way to do that is to add these two utility methods:

public void addComment(PostComment comment) {
    comments.add(comment);
    comment.setPost(this);
}

public void removeComment(PostComment comment) {
    comments.remove(comment);
    comment.setPost(null);
}

The addComment and removeComment methods ensure that both sides are synchronized. So, if we add a child entity, the child entity needs to point to the parent and the parent entity should have the child contained in the child collection.

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to hibernate

Hibernate Error executing DDL via JDBC Statement How does spring.jpa.hibernate.ddl-auto property exactly work in Spring? Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed JPA Hibernate Persistence exception [PersistenceUnit: default] Unable to build Hibernate SessionFactory Disable all Database related auto configuration in Spring Boot Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] HikariCP - connection is not available Hibernate-sequence doesn't exist How to find distinct rows with field in list using JPA and Spring? Spring Data JPA and Exists query

Examples related to jpa

No converter found capable of converting from type to type How does spring.jpa.hibernate.ddl-auto property exactly work in Spring? Deserialize Java 8 LocalDateTime with JacksonMapper Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed How to beautifully update a JPA entity in Spring Data? JPA Hibernate Persistence exception [PersistenceUnit: default] Unable to build Hibernate SessionFactory How to return a custom object from a Spring Data JPA GROUP BY query How to find distinct rows with field in list using JPA and Spring? What is this spring.jpa.open-in-view=true property in Spring Boot? Spring Data JPA and Exists query

Examples related to one-to-many

Laravel - Form Input - Multiple select for a one to many relationship JPA OneToMany and ManyToOne throw: Repeated column in mapping for entity column (should be mapped with insert="false" update="false") What is the meaning of the CascadeType.ALL for a @ManyToOne JPA association What's the difference between @JoinColumn and mappedBy when using a JPA @OneToMany association deleted object would be re-saved by cascade (remove deleted object from associations) Difference between one-to-many and many-to-one relationship Hibernate throws MultipleBagFetchException - cannot simultaneously fetch multiple bags Difference Between One-to-Many, Many-to-One and Many-to-Many? What is “the inverse side of the association” in a bidirectional JPA OneToMany/ManyToOne association? JPA - Persisting a One to Many relationship

Examples related to mappedby

What is “the inverse side of the association” in a bidirectional JPA OneToMany/ManyToOne association?