我在 Java Hibernate 中使用 SINGLE_TABLE 继承策略,这里是设置:
Class A
@Cascade(CascadeType.DELETE_ORPHAN, CascadeType.ALL)
List<B> Bs;
B 有一个扩展 B 的子类 Ba。Ba 有一个 B 没有的额外字段。我这样做的原因是只有 Ba 对象(少得多)应该关心这个额外的字段,我想避免在每个 B 对象上都有它的开销。
在保存期间,按照我们的设置方式,我们必须更新以前的 B 对象字段(而不是仅仅更改引用)。所以我们不能做 List of Bs = List of Changed Bs,我们必须通过主键找到每个单独的 B 并更新字段,所以像 B.fields = changedB.fields
出现这个异常的时候是在保存的时候,之前的B对象需要保存为一个带有extra字段的Ba。反向(将以前的 Ba 对象保存到 B)很好,我可以将该额外字段设置为 null 或向下转换。但我似乎找不到将 B 对象变成 Ba 的方法。
我试过了
- 在保存之前从列表中删除 B 并添加一个 Ba,这就是我遇到此异常的时候。
- 我什至还尝试将所有字段从 B 交换到需要转换为 B 的 Ba,反之亦然,但这也没有用,我得到了一个异常,因为我更改了这些对象的 Pk .
最佳答案
期间 Session flush the DML operation order是:
- 插入
- 更新
- 集合元素的删除
- 集合元素的插入
- 删除
因此,即使您删除该元素并添加一个新元素,插入也会在删除之前运行,从而抛出约束违反异常。
要使其正常工作,您需要在删除之后和将新元素添加回子集合之前手动刷新:
a.removeChild(b);
session.flush();
a.addChild(ba);
remove/addChild 是设置双向关联两侧的实用程序,如果在您的域模型中是这种情况的话。
关于java - 似乎无法摆脱 NonUniqueObjectException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26265539/