我正在尝试更新 Java 实体的集合,但 Hibernate 执行批处理更新的顺序导致约束冲突异常。我将使用以下示例来解释这种情况。
实体学生国际标识字符串名称字符串桌面标识
规则:2名学生不能拥有同一张桌子
第一笔交易:插入 2 名学生,如下所示学生 1编号:1名称:ABC桌面编号:D1
学生 2编号:2名称:德福桌面 ID: D2
现在在此之后,我决定更新两个学生实体以交换他们的桌子我发送了更新的学生实体的集合到休眠更新学生 1编号:1名称:ABC桌面编号:D2
学生 2编号:2名称:德福桌面 ID: D1
但这会导致约束冲突异常,因为我认为更新一次进行一条记录。
我正在使用 JTA 实体管理器来管理交易。我的更新代码看起来像这样
updateMultiple(Collection<Student> updatedStudents)
for (final Student student: updatedStudents)
{
final Student st= this.entityManager.getReference(Student.class, Student.getId());
student.merge(st);
}
this.entityManager.flush();
return breakClauseDtos;
问题的根源很清楚:数据库在执行 SQL 语句时而不是在提交时检查约束。执行第一个 SQL 语句时,违反了约束。
您可以先从学生 1 中移除桌子,然后将其分配给学生 2,然后再将自己的描述交给学生 1 来解决此问题。这意味着三个 SQL 语句(比必要的多一个),然后您可能必须在每次更新后刷新会话(Hibernate 重新排序 SQL 语句,这可能会干扰您的手动顺序)。
但更好的解决方案是更正数据模型中的问题。
如果每张课桌只能由一个学生拥有,那么课桌与学生之间就有 n:1 的关系。Desk 需要学生的 ID 作为外键。无需定义额外的约束。现在更改办公桌意味着更改办公桌记录中的学生 ID。这只能通过两个更新语句来完成。