休眠 - 清除收集与全删除,孤儿,然后添加到它会导致ConstraintViolationException
-
20-09-2019 - |
题
我有这些实体
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()
(插入),但反之亦然之前执行add()
(删除)时,它首先试图插入,获得一个ConstraintViolationException
我知道加入session.flush()
后有点bars.clear();
,可以解决这个问题,但在这种情况下,我有一个非丑陋的方式没有访问会话。
所以是齐平是唯一的解决办法?或者是有一个尊重的动作的顺序一个Hibernate版本?
<强>更新强> 顺便说一句,提领该集合将导致HibernateException的从 https://www.hibernate.org/ 117.html#A3 :
我得到HibernateException的:不要 解引用一个集合 级联= “全删除-孤儿”此 如果您加载一个对象会发生 级联=“全删除,孤儿” 集合,然后删除 参考集合。别 更换此集合,使用clear() 所以孤儿删除算法可以 检测更改。
解决方案
我想没有替代冲洗
从这里:
<强>休眠违反唯一约束!强>
Hibernate是不是很 巧用唯一约束,因为它 与外键。有时候你 可能需要给一点提示。
一个唯一约束违反能 如果两个对象都存在发生 更新,一个是“释放”的值 另一种是“获得”相同 值。一种解决方法是为齐平()的所述 更新后的会话手动 第一对象和更新前 第二。
(这种问题很少出现在 做法。)
其他提示
如果你想避免在这里冲洗会议,尝试更换整个列表(new List<Bar>()
而不是Clear()
)。休眠应该增加新的前实际删除在一杆中的所有项目。只是一种尝试,不知道是否可行。
如果您使用的是Oracle,你也可以使用延迟约束,直到事务被提交推迟的约束检查。不知道是否/如何被其他数据库的支持。