9

我收到一个错误:

不要使用 cascade="all-delete-orphan" 更改对集合的引用

在尝试以下操作时:

beginTx();
Parent parent = new Parent();
Child child = new Child();
parent.addChild(child);
getSession().save(parent);
commitTx();
closeSession();

beginTx();
//id is the primary key
child.setID(null);
getSession().update(child);
commitTx();
closeSession();

父母和孩子通过one-to-manycascade = ' all-delete-orphan' 相关联。

class Parent {
Set child;
}


<set name="child" table="Child" cascade="all-delete-orphan" inverse="true">
    <key column="FK"></key>
    <one-to-many class="Child"/>
</set>

知道为什么会抛出这个异常吗?即使实体处于分离状态,为什么在主键上设置 null 会导致此异常?

4

4 回答 4

10

如果您使用 加载具有集合的实体cascade=all-delete-orphan,然后删除对集合的引用,通常会发生此异常。

不要替换此集合。始终使用collection.clear()删除所有关联的子条目,以便孤儿删除算法可以检测到更改。如果你想删除任何特定的孩子,你只需要把它从集合中删除。一旦从集合中删除,它将被视为孤儿并将被删除。

于 2013-09-20T08:22:39.310 回答
3

对于异常不要更改对具有 cascade="all-delete-orphan" 的集合的引用。您使用child.setID(null);更改 ID 会导致异常。

hibernatePersistentSet用来执行异常检查,所以你可以这样做:

child.setID(null);
parent.child=new HashSet(parent.child)

使用 HashSet 代替 PersistentSet

于 2016-07-11T06:17:24.213 回答
2

这是因为关闭事务不会关闭当前会话。这意味着它child仍然是当前会话的一部分,Hibernate 仍然会认为它是同一个孩子,并会尝试id在数据库中将其归零。

如果要使child对象瞬态,则应evict()在其上使用。

于 2015-11-11T13:44:10.470 回答
0

你可以得到这个的另一个原因是因为EntityManager.detach实体图中的一个对象EntityManager.flush(最终可能会发生)在这种情况下,由于它与实体图分离,它将尝试再次创建一个新对象,但它处于奇怪的状态并且如果你修改它,你会得到以下错误

不要更改对集合的引用...

于 2022-02-11T07:00:17.707 回答