Search code examples
javaspringhibernatespring-data

How to add child record in a Unidirectional @OneToMany without retrieving previous records


I'm dealing with a unidirectional @OneToMany association that utilizes the "author_book" table as an intermediate table. However, when attempting to add a new Book to an Author in order to generate a new entry in the "author_book" table, I'm having to first retrieve all previous Books. This process becomes time-consuming, especially when an author has a substantial number of books. In my case, I cannot use a bidirectional @OneToMany association. Is there a more efficient way to accomplish this using a unidirectional approach?

Author Entity:

@Entity
public class AuthorEntity {
   @Id
   private long id;

   @OneToMany
   @JoinTable(name = "author_book", joinColumns = @JoinColumn(name = "id_author"),
              inverseJoinColumns = @JoinColumn(name = "id_book"))
   private Set<BookEntity> books;
}

And Book Entity:

@Entity
public class BookEntity {
   @Id
   private long id;
}

Adding new Book

public void addBook(BookEntity book) {
    AuthorEntity author = authorRepository.findById(authorId);
    author.getBooks().add(book);
    entityManager.merge(author);
}

Solution

  • 1. Change to @ManyToOne Relationship:

    One approach is to modify the relationship from @OneToMany to @ManyToOne. By doing this, you can establish a relationship from the book to its author. When adding a new book, you can simply set the author of the book, and Hibernate will efficiently execute a single insert statement. This method works well if you don't need to navigate from the author to their books directly.

    BookEntity b = new BookEntity();
        AuthorEntity a = em.getReference(AuthorEntity.class, 1L);
        b.setAuthor(a);
        b.setId(342L);
        em.persist(b);
    

    2. Native SQL Queries:

    Another option is to create a native SQL query to perform the insertion directly. It will not load the entire collection because you will just insert the entity manually without loading it first.

    Similar question: Hibernate - How to persist a new item in a Collection without loading the entire Collection