Hibernate Tips: How to delete child entities from a many-to-one association

By Thorben Janssen

Association Mapping, Mapping

Hibernate Tips is a series of posts in which I describe a quick and easy solution for common Hibernate questions. If you have a question for a future Hibernate Tip, please leave a comment below.

Question:

My domain model contains a many-to-one association in which the child entity can’t exist without its parent. Can Hibernate automatically delete the child entity if I remove its association to the parent?

Solution:

Yes, the JPA specification provides the orphanRemoval feature for these use cases. When you activate it on the association, Hibernate removes a child entity when you remove its association to the parent entity.

Let’s take a look at an example.

In most online book stores, customers can review the offered books. You can model that with a Book and a Review entity and a one-to-many association between them.

It doesn’t make any sense to store a Review that’s not associated with a Book. So, you should set the orphanRemoval attribute of the @OneToMany association to true. And you also need to set the cascade attribute to CascadeType.PERSIST or CascadeType.ALL.

@Entity
public class Book {

	@OneToMany(mappedBy = "book", orphanRemoval = true, cascade = CascadeType.PERSIST)
	private List<Review> reviews = new ArrayList<Review>();
	
	...
}

When you now remove a Review entity from the association that’s modeled by the List reviews attribute, Hibernate will delete the Review entity from the database.

em = emf.createEntityManager();
em.getTransaction().begin();

Book b = em.find(Book.class, 1L);
b.getReviews().remove(0);

em.getTransaction().commit();
em.close();

As you can see in the following log messages, Hibernate performs 2 SQL SELECT statements to get the Book entity with id 1 and all associated Review entities. And when I commit the transaction, it also performs an SQL DELETE operation to remove the Review entity from the database.

14:12:57,197 DEBUG [org.hibernate.SQL] - select book0_.id as id1_0_0_, book0_.title as title2_0_0_, book0_.version as version3_0_0_ from Book book0_ where book0_.id=?
14:12:57,201 DEBUG [org.hibernate.SQL] - select reviews0_.fk_book as fk_book3_1_0_, reviews0_.id as id1_1_0_, reviews0_.id as id1_1_1_, reviews0_.fk_book as fk_book3_1_1_, reviews0_.comment as comment2_1_1_ from Review reviews0_ where reviews0_.fk_book=?
14:12:57,212 DEBUG [org.hibernate.SQL] - delete from Review where id=?

Learn more:

If you want to learn more about association mappings with JPA and Hibernate, you should also take a look at the following posts:

 

Hibernate Tips Book


Get more recipes like this one in my new book Hibernate Tips: More than 70 solutions to common Hibernate problems.

It gives you more than 70 ready-to-use recipes for topics like basic and advanced mappings, logging, Java 8 support, caching and statically and dynamically defined queries.

Get it now as a paperback, ebook or PDF.

Tags

Association Mapping, Mapping


About the author

Thorben is an independent consultant, international speaker, and trainer specialized in solving Java persistence problems with JPA and Hibernate.
He is also the author of Amazon’s bestselling book Hibernate Tips - More than 70 solutions to common Hibernate problems.

Books and Courses

Coaching and Consulting

Leave a Repl​​​​​y

Your email address will not be published. Required fields are marked

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  1. Thank you for the informative post.

    I have similar mapping. But I am not able to delete directly Review.

    Removing via collection works fine.

    Review r = em.find(Rdeview.class, 1L);
    em.remove(r);

    Do you have any suggestions?

    Thanks,
    Datta

    1. In addition, I have set nullable false on JoinColumn

      @ManyToOne(optional = false)
      @JoinColumn(name = “id_review”, nullable = false)
      public Review getReview() {
      return review;
      }

      1. Hi Datta,

        please share your association mapping, the code which removes the entity and the exception. You can either do that here or on StackOverflow.

        Regards,
        Thorben

  2. Hi,

    I am in some sort of the same situation here, but the other way around. In my case I am not allowed to delete a book that has a review, is that possible to do that in hibernate?

    Br Jakob

    1. yes, you can.

      Actually this entire operation is done by CASCADE, so if you don’t mention CASCADE TYPE it will throw Error definitely while deleting book before removing all reviews.

      Hope this will help.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}