Search code examples
javahibernatehibernate-onetomany

Hibernate How to correctly delete children in @OneToMany?


I have a very simple unidirectional @OneToMany from a Parent object to a List of children with CascadeType.ALL. How would I correctly remove and delete one of the children?

Simply calling remove(child) on the List and then session.saveOrUpdate(parent) of course does not work and the child is not deleted in the database unless I specify orphan removal.

As an alternative to orphan removal, would it be correct if I session.delete(child) to delete it in the DB, then remove(child) from the List and do I then have to session.refresh(parent) so my parent object in memory has the right state?

How would I correctly remove the child and have it deleted in the database without orphan removal?

I am currently thinking about this in my ParentDao:

public void removeChild(Parent parent, Child child) {
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx = null;
    try {
        session.beginTransaction();

        session.delete(child);

        session.getTransaction().commit();

        parent.getChildren().remove(child);
        session.refresh(parent);
    } catch (RuntimeException e) {
        if (tx != null) {
            tx.rollback();
        }
        throw e;
    } finally {
        session.close();
    }
}

Solution

  • As you area going to do the @Cascade(DELETE_ORPHAN) (from Hibernate) manually, here is the code that does pretty much the same behavior.

    Entities:

    class Library {
    
      @Id
      private Integer id;
    
      @OneToMany
      private List<Book> books;
    
      // getters and setters    
    }
    
    class Book {
    
      @Id
      private Integer id; 
    
      @ManyToOne
      private Libraby library;
    
      // getters and setters
    }
    

    And a simple example:

    session.beginTransaction();
    
    // load a library with ID = 1
    Library library = session.get(Library.class, 1);
    
    // assuming that your library has two books
    Book book = library.getBooks().get(0); //gets the first book
    library.getBooks().remove(0); // Remove this book from the library
    session.delete(book);
    
    session.getTransaction().commit();
    

    And your Book will be deleted from the database and the lisf othe parent will be updated as well.