There are 3 ways to map One-To-Many and Many-To-One relationship in JPA and Hibernate by using @OneToMany and @ManyToOne, including

  • Bidirectional mapping with @OneToMany and @ManyToOne

  • Unidirectional mapping with @ManyToOne

  • Unidirectional mapping with @OneToMany

This guide will show you how to map along with the pros and cons of each approach

Consider the relationship between the library and books. One library may have many books, one book can only be managed by one library

Bidirectional mapping with @OneToMany and @ManyToOne

@OneToMany would be placed on a collection association of an entity (or the One side) with the mappedBy attribute pointing to the relationship owner

@Entity
public class Library {  
    ...

    @OneToMany(mappedBy = "library", cascade = CascadeType.ALL)
    private Set<Book> books = new HashSet<>();

    ...
}

@ManyToOne would be placed on the single item association of an entity (or the relationship owner; the table with a foreign key column in the underlying database)

@Entity
public class Book {  
    ...

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "library_id")
    private Library library;

    ...
}

@JoinColumn specifies the foreign key column. It is optional for bidirectional mapping, default name to the underscore string join of the association field name and its primary key column name

On the opposite, the mappedBy attribute on @OneToMany is required to specify for bidirectional mapping. If mappedBy is absent, JPA and Hibernate will create a redundant join table library_books

+------------+---------+------+-----+---------+-------+
| Field      | Type    | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| library_id | int(11) | NO   | PRI | NULL    |       |
| books_id   | int(11) | NO   | PRI | NULL    |       |
+------------+---------+------+-----+---------+-------+

Pros and cons

  • Both entities of the relationship can quickly access and cascade CRUD operations to each other

  • @OneToMany can cause a performance issue on a large child collection

Hands-on tutorials

Unidirectional mapping with @ManyToOne

@ManyToOne would be placed on a single item association of an entity (or on the table with a foreign key column in the underlying database). There is no child collection association mapping on the parent entity

@Entity
public class Book {  
    ...

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "library_id")
    private Library library;

    ...
}

@JoinColumn specifies the foreign key column. It is optional for unidirectional @ManyToOne mapping, default name to the underscore string join of the association field name and its primary key column name

Pros and cons

  • Avoid the potential performance issue of @OneToMany

  • The parent entity can not navigate or cascade CRUD operations to the child collection. However, you can do it manually via JPQL query

Hands-on tutorials

Unidirectional mapping with @OneToMany

@OneToMany would be placed on a child collection of an entity (or the One side) with @JoinColumn and without mappedBy

We don't need to specify the mappedBy attribute on unidirectional @OneToMany as there is no parent association mapping on the child entity

@Entity
public class Library {  
    ...

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "library_id")
    private Set<Book> books = new HashSet<>();

    ...
}

@JoinColumn is required to specify the foreign key column for unidirectional @OneToMany. If @JoinColumn is absent, JPA and Hibernate will create a redundant join table library_books

+------------+---------+------+-----+---------+-------+
| Field      | Type    | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| library_id | int(11) | NO   | PRI | NULL    |       |
| books_id   | int(11) | NO   | PRI | NULL    |       |
+------------+---------+------+-----+---------+-------+

Pros and cons

  • The parent entity can quickly access and cascade CRUD operations to child collection

  • The child entity cannot navigate the parent entity

  • @OneToMany can cause a performance issue on a large child collection

In this article, we had a quick look at various ways to map One to Many and Many to One relationship in JPA and Hibernate along with the notes on their pros and cons