我有这些实体
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)
local_identifier
parent_id
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
clear()
add()
ConstraintViolationException
我知道session.flush()在之后添加一点bars.clear();可以解决此问题,但是在这种情况下,我无法以非丑陋的方式访问会话。
session.flush()
bars.clear();
那么冲洗是唯一的解决方案吗?还是有一个Hibernate版本尊重操作顺序?
更新: 顺便说一句,取消引用集合将导致来自https://www.hibernate.org/117.html#A3的HibernateException :
我得到了HibernateException:不要用cascade =“ all-delete-orphan”取消引用集合。 如果您加载了带有cascade =“ all-delete- orphan”集合的对象,然后删除对该集合的引用,则会发生这种情况。不要替换此集合,请使用clear(),以便孤立删除算法可以检测到您的更改。
我想没有其他方法可以冲洗
从这里:
Hibernate违反了唯一约束! Hibernate的唯一约束并不像外键那么聪明。有时您可能需要给出一些提示。 如果两个对象都被更新,一个对象在“释放”一个值,而另一个对象在“获取”相同的值,则可能发生唯一约束冲突。一种解决方法是在更新第一个对象之后并在更新第二个对象之前手动 冲洗 会话。 (这种问题在实践中很少发生。)
Hibernate违反了唯一约束!
Hibernate的唯一约束并不像外键那么聪明。有时您可能需要给出一些提示。
如果两个对象都被更新,一个对象在“释放”一个值,而另一个对象在“获取”相同的值,则可能发生唯一约束冲突。一种解决方法是在更新第一个对象之后并在更新第二个对象之前手动 冲洗 会话。
(这种问题在实践中很少发生。)