Hibernate-清除包含所有删除孤立项的集合,然后将其添加到集合中会导致ConstraintViolationException
我有这些实体Hibernate-清除包含所有删除孤立项的集合,然后将其添加到集合中会导致ConstraintViolationException,hibernate,unique-constraint,Hibernate,Unique Constraint,我有这些实体 class Foo{ Set<Bar> bars; } class Bar{ Foo parent; String localIdentifier; } 使用它们的代码是: //foo is persistent, foo id = 1 Bars bars = foo.getBars(); bars.clear(); // bars contained 1 item [parent_id = 1, local_identifier = "a"
class Foo{
Set<Bar> bars;
}
class Bar{
Foo parent;
String localIdentifier;
}
使用它们的代码是:
//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没有按照调用的顺序执行。它不会在add()
(insert)之前执行clear()
(delete),反之亦然,它首先尝试插入,得到一个ConstraintViolationException
我知道在bar.clear()之后添加一点session.flush()
,可以修复此问题,但在这种情况下,我无法以非丑陋的方式访问会话
那么,冲洗是唯一的解决办法吗?或者是否有一个遵守操作顺序的Hibernate版本
更新:
顺便说一句,取消对集合的引用将导致以下对象的HibernateException:
我会冬眠例外:不要
取消对集合的引用
cascade=“全部删除孤立项”此
如果加载对象时使用
a cascade=“全部删除孤立项”
集合,然后删除
对集合的引用。不要
若要替换此集合,请使用clear()
因此,孤儿删除算法可以
检测您的变化
如果要避免刷新此处的会话,请尝试替换整个列表(
new list()
,而不是Clear()
)。Hibernate实际上应该在添加新项目之前一次性删除所有项目。只是一次尝试,不确定它是否有效。我想除了冲水没有别的选择
发件人:
Hibernate违反了唯一约束
Hibernate并不完全是这样
巧妙地使用独特的约束
是用外键的。有时候你
可能需要给点提示
可能会出现唯一的约束冲突
如果两个对象同时处于活动状态,则发生
更新后,一个是“释放”一个值
另一个是“获得”相同的信息
价值一种解决方法是刷新
更新会话后手动执行会话
第一个对象,在更新
第二
(这种问题在中国很少发生
练习。)
如果您使用的是oracle,那么还可以使用可延迟约束来推迟对约束的检查,直到提交事务为止。不确定其他数据库是否/如何支持此功能。我遇到了一个稍微类似的问题,在特定条件下,我在子表上有一个唯一的索引。所以我的问题是,当我删除一条满足这个条件的记录,然后添加另一条将恢复那个条件的记录时,我得到了唯一的索引问题 经过多次尝试和建议。我不喜欢删除后和添加前刷新的想法,但我认为它会起作用,我找到了一个约束解决方案,删除了唯一索引(因为我实际上不需要对列进行索引),该索引确实起作用: (关于postgres数据库) 最初推迟是这里的关键 我使用的示例代码:
//Transaction 1
Foo parent = new Foo('some-id');
boolean condition = true;
Bar c = new Bar('some-id', parent, condition);
parent.getChildren().add(c);
fooService.save(parent); //children list are cascaded
。。。后来
//Transaction 2
boolean condition = true;
Foo parent = fooSerice.findById('some-id'); //children list is eagerly fetched
Bar c1 = parent.getChildren().stream().filter(c -> c.getId().equals("some-id")).findFirst().get();
Bar c2 = new Bar('some-id1', parent, condition);
parent.getChildren().remove(c1);
parent.getChildren().add(c2);
我认为冲洗是唯一的选择。
ALTER TABLE bar ADD CONSTRAINT bar_uc
EXCLUDE (parent_id WITH =) WHERE (condition = true) INITIALLY DEFERRED;
//Transaction 1
Foo parent = new Foo('some-id');
boolean condition = true;
Bar c = new Bar('some-id', parent, condition);
parent.getChildren().add(c);
fooService.save(parent); //children list are cascaded
//Transaction 2
boolean condition = true;
Foo parent = fooSerice.findById('some-id'); //children list is eagerly fetched
Bar c1 = parent.getChildren().stream().filter(c -> c.getId().equals("some-id")).findFirst().get();
Bar c2 = new Bar('some-id1', parent, condition);
parent.getChildren().remove(c1);
parent.getChildren().add(c2);