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

the*_*e19 2 java database hibernate

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

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

  1. 执行查找以通过Hibernate从数据库中获取持久对象
  2. 修改对象
  3. 通过Hibernate更新对象

以下是我正在做的一些快速代码:

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);
   }
}
Run Code Online (Sandbox Code Playgroud)

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

org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: my.Foo.list
Run Code Online (Sandbox Code Playgroud)

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

Mac*_*Mac 5

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

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

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

而不是手动调整托管对象的列表,而是使用merge(foo)非托管实例更新持久化实例的状态.从Hibernate手册:

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

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