Hibernate How to correctly delete children in @One

2019-06-11 16:25发布

问题:

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();
    }
}

回答1:

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.



回答2:

Can you try below code? Removing from list before commit.

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

        parent.getChildren().remove(child); 
        session.delete(child);

        session.getTransaction().commit();


       // session.refresh(parent); // this is not required
    } catch (RuntimeException e) {
        if (tx != null) {
            tx.rollback();
        }
        throw e;
    } finally {
        session.close();
    }
}