【问题标题】:Hibernate How to correctly delete children in @OneToMany?Hibernate如何正确删除@OneToMany中的孩子?
【发布时间】:2014-10-23 15:59:20
【问题描述】:

我有一个非常简单的单向@OneToMany,从父对象到 CascadeType.ALL 的子对象列表。我将如何正确删除和删除其中一个孩子?

只需在 List 上调用 remove(child) 然后 session.saveOrUpdate(parent) 当然不起作用,并且除非我指定孤儿删除,否则不会在数据库中删除子项。

作为孤立删除的替代方法,如果我 session.delete(child) 在数据库中删除它,然后从列表中删除(child) 并且我必须 session.refresh(parent) 所以是否正确我在内存中的父对象有正确的状态?

我如何正确删除子项并将其从数据库中删除而不进行孤立删除?

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

【问题讨论】:

    标签: java hibernate hibernate-onetomany


    【解决方案1】:

    当您打算手动执行 @Cascade(DELETE_ORPHAN)(来自 Hibernate)时,这里是执行几乎相同行为的代码。

    实体:

    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
    }
    

    还有一个简单的例子:

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

    您的 Book 将从数据库中删除,并且父级的 lisf 也将更新。

    【讨论】:

    • 实际上我的主要问题是:如果没有 DELETE_ORPHAN,我将如何手动完成?
    • 我正在努力更好地理解它。
    • 哦,好的,我将更改代码以使其更易于理解。一秒
    • 好的,谢谢!但是如果我不刷新(图书馆),然后添加一本新书并再次直接调用 saveOrUpdate(图书馆),我得到一个 org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0];实际行数:0;预期:1 所以我想我需要先调用 refresh() 。从集合中移除已删除的对象是不够的。
    • 哦,是的,如果你之后要添加另一个对象,那么你需要刷新它。此示例仅显示如何从集合和数据库中删除。事实上,我建议,在你运行这段代码之后,通过刷新它或再次使用这个库的 find 方法来重新加载你的对象;)
    【解决方案2】:

    你能试试下面的代码吗?在提交之前从列表中删除。

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

    【讨论】:

    • 谢谢!但是如果我不刷新(父),然后添加一个新的子并再次直接调用 saveOrUpdate(parent),我得到一个 org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0];实际行数:0;预期:1 所以我想我需要先调用 refresh() 。从集合中移除已删除的对象是不够的。
    猜你喜欢
    • 1970-01-01
    • 2011-01-01
    • 2016-04-22
    • 2015-05-05
    • 2017-06-07
    • 2015-11-03
    • 2022-08-13
    • 2017-06-23
    • 2020-11-14
    相关资源
    最近更新 更多