我有这些实体
class Foo{
Set<Bar> bars;
}
class Bar{
Foo parent;
String localIdentifier;
}
有了这个映射(对不起,没有注释,我是老式的):
<class name="Foo">
...
<set name="bars" cascade="all-delete-orphan" lazy="false" inverse="true">
<key>...</key>
<one-to-many class="Bar"/>
</set>
</class>
<class name="Bar">
...
<property name="localIdentifier" column="local_identifier"/>
<many-to-one name="parent" column="parent_id" />
</class>
我对 2 列也有唯一约束:local_identifier
和parent_id
(不是每列的唯一约束,而是包含两者的单个唯一约束,例如,不允许有 2 行具有相同父级和相同 localIdentifier)
alter table bar add constraint unique_bar unique (parent_id, local_identifier)
而使用它们的这段代码:
//foo is persistent, foo id = 1
Bars bars = foo.getBars();
bars.clear(); // bars contained 1 item [parent_id = 1, local_identifier = "a"]
Bar newBar = new Bar();
newBar.setParent(foo);
newBar.setLocalIdentifier("a");
bars.add(newBar);
现在,出于某种原因,Hibernate 不会按照调用顺序执行操作。它不会clear()
在 (insert) 之前执行 (delete),add()
反之亦然,它首先尝试插入,得到一个ConstraintViolationException
session.flush()
我知道在 之后添加一点bars.clear();
,可以解决这个问题,但在这种情况下,我无法以非丑陋的方式访问会话。
那么flush是唯一的解决方案吗?还是有尊重动作顺序的休眠版本?
更新: 顺便说一句,取消引用集合将导致来自https://www.hibernate.org/117.html#A3的 HibernateException :
我得到 HibernateException: Don't dereference a collection with cascade="all-delete-orphan"如果您使用 cascade="all-delete-orphan" 集合加载对象然后删除对集合的引用,则会发生这种情况。不要替换此集合,请使用 clear() 以便孤儿删除算法可以检测到您的更改。