【发布时间】:2020-02-13 19:49:48
【问题描述】:
我的数据库中有 3 个实体,我们称它们为 A、B 和 C。
A 和 B 彼此共享多对多关系。 A 有 SortedSet 的 Bs,但 B 不引用 A(没有收集或配置)。所以我们有以下内容。
// Inside class A
@ManyToMany
@JoinTable(name = "a_b",
joinColumns = {@JoinColumn(name = "a_id")},
inverseJoinColumns = {@JoinColumn(name = "b_id")})
@LazyCollection(LazyCollectionOption.FALSE)
@SortNatural
private SortedSet<B> bSet = new TreeSet<B>();
B 和C 彼此之间存在一对多的关系(1 个B 到多个Cs)。 C 的实体中有一个 B,但 B 没有引用它的许多 C 实体。所以我们有以下
// Inside class C
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "b_id", nullable = false, updatable = true)
protected B b;
我们有一个同步进程,每晚运行一个作业来更新A 实体及其与B 实体的关联(不会经常更改)。我们最终会得到类似于以下内容的内容(实际上,DAO、服务等要复杂得多)。
// Get the A value to be updated
A aToUpdate = entityManager.find(A.class, idForA);
// Out of scope of the question, but we need to figure out B via a string field on C
C cValue = myDao.getByProperty("fieldName", fieldValue);
// Determine the B values to set on aToUpdate
B bToSetOnA = cValue.getB();
TreeSet<B> bSet = new TreeSet<>();
bSet.add(bToSetOnA);
// Update aToUpdate
aToUpdate.setBSet(bSet);
aToUpdate = entityManager.merge(aToUpdate);
entityManager.flush();
发生这种情况时,会出现以下错误。
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (Sync Thread)
Duplicate entry 'myAId-almostMyBId' for key 'uk_a_b'
一个有趣的事情是almostMyBId 比实际的B ID 少1 个字符。但是 a_b 表中只有完整的 ID。
当我查看代码库时,a_b 表的索引上有一个uk_a_b 约束。这是来自 liquibase。
<createIndex indexName="uk_a_b" tableName="a_b" unique="true">
<column name="a_id"/>
<column name="b_id"/>
</createIndex>
如果我删除 aToUpdate.setBSet(bSet); 行,错误就会消失。
我添加了日志记录并确认新 bSet 的 ID 与 aToUpdate 上的旧 ID 相同。
不知何故,Hibernate 似乎正在尝试重新添加关联,即使我们正在进行合并并且关联并没有真正改变。
我已经尝试在这里和那里更改一些 CascadeType 和 FetchType 的东西,但错误似乎并没有消失。有人知道发生了什么吗?
【问题讨论】:
标签: java hibernate persistence liquibase cascade