简体   繁体   English

Hibernate如何正确删除@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. 我有一个非常简单的单向@OneToMany,从Parent对象到具有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. 只需在List上先调用remove(child),然后再调用session.saveOrUpdate(parent),当然这是行不通的,除非我指定了孤立删除,否则不会在数据库中删除该child。

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? 作为孤立删除的替代方法,如果我session.delete(child)将其删除到数据库中,然后从List中删除(child),然后我必须进行session.refresh(parent),那么我的父对象是否正确?在内存中有正确的状态?

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: 我目前正在我的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();
    }
}

As you area going to do the @Cascade(DELETE_ORPHAN) (from Hibernate) manually, here is the code that does pretty much the same behavior. 当您打算手动执行@Cascade(DELETE_ORPHAN)(来自Hibernate)时,这里的代码几乎具有相同的行为。

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. 并且您的“图书”将从数据库中删除,父目录也将更新。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM