在Hibernate中更新包含列表的对象

时间:2011-09-22 23:01:39

标签: java database hibernate

在我的GWT应用程序中,我将一个Object传递给服务器,以便使用Hibernate进行持久化。此Object包含另一个对象的列表。列表中的每个元素都包含一个Map,它是另一个Hibernate表。

为了做这个交易,我的理解是我必须先:

  1. 执行查找以通过数据库从数据库中获取持久对象 Hibernate
  2. 修改对象
  3. 通过Hibernate更新对象
  4. 以下是我正在做的一些快速代码:

    public void saveOrUpdateObject(final Foo foo)
    {
       Session session = sessionFactory.getCurrentSession();
       session.beginTransaction();
    
       Object lookup = myDAO.getObject(foo.getUniqueValue());
    
       if (lookup != null) {
          lookup.getList().clear();
          lookup.addAll(foo.getList());
    
          myDAO.update(lookup);
       }
       else {
          myDAO.save(foo);
       }
    }
    

    使用这种方法,我偶尔会得到一个HibernateException:

    org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: my.Foo.list
    

    使用Hibernate更新包含集合的Object的正确方法是什么?

1 个答案:

答案 0 :(得分:5)

问题与托管和非托管对象有关:

  • lookup是一个托管对象, lookup.list及其中的所有内容
  • foo不是托管对象,foo.list
  • 中也没有

当您致电lookup.getList().clear()时,您发信号通知Hibernate需要删除该托管列表中的所有内容(由于all-delete-orphan级联)。然而,然后你回来并向该(托管)列表中添加一些东西,包括可能已经存在的一些东西。 Hibernate感到困惑并抛出异常。

使用merge(foo)来更新持久化实例与非托管实例的状态,而不是手动调整托管对象的列表。来自Hibernate manual

  

如果存在具有当前与会话关联的相同标识符的持久性实例,则将给定对象的状态复制到持久性实例

合并将确定哪个状态更新的责任放在Hibernate上。