在我的GWT应用程序中,我将一个Object传递给服务器,以便使用Hibernate进行持久化。此Object包含另一个对象的列表。列表中的每个元素都包含一个Map,它是另一个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);
}
}
使用这种方法,我偶尔会得到一个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的正确方法是什么?
答案 0 :(得分:5)
问题与托管和非托管对象有关:
当您致电lookup.getList().clear()
时,您发信号通知Hibernate需要删除该托管列表中的所有内容(由于all-delete-orphan
级联)。然而,然后你回来并向该(托管)列表中添加一些东西,包括可能已经存在的一些东西。 Hibernate感到困惑并抛出异常。
使用merge(foo)
来更新持久化实例与非托管实例的状态,而不是手动调整托管对象的列表。来自Hibernate manual:
如果存在具有当前与会话关联的相同标识符的持久性实例,则将给定对象的状态复制到持久性实例
合并将确定哪个状态更新的责任放在Hibernate上。