我正在尝试更新一个Java实体的集合,但是Hibernate执行批量更新的顺序导致了一个违反约束的异常。我将用下面的例子来解释这种情况。
实体学生Int id String名称String String deskID
规则:两个学生不能共用一张课桌
第一笔交易:按如下方式插入2名学生1学生Id:1姓名:ABC DeskId:D1
学生2 Id:2姓名:DEF DeskId: D2
现在,我决定更新这两个学生实体以交换它们的课桌,并将更新后的学生实体的集合发送到hibernate,更新学生1 Id:1姓名:ABC DeskId:D2
学生2 Id:2姓名:DEF DeskId: 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;
发布于 2012-10-02 12:08:01
问题的根源很清楚:数据库在执行SQL语句时而不是在提交时检查约束。当执行第一个SQL语句时,就违反了约束。
您可以先将学生1的桌子移走,然后将其分配给学生2,然后将学生1的桌子交给学生1,这样就可以绕过这个问题。这意味着需要三条SQL语句(多出一条),然后可能必须在每次更新后刷新会话(Hibernate会对SQL语句进行重新排序,这可能会干扰您的手动排序)。
但更好的解决方案是纠正数据模型中的问题。
如果每张课桌只能归一个学生所有,那么课桌与学生之间存在n:1的关系。Desk需要将学生的id作为外键。不需要定义额外的约束。现在,更换课桌意味着更改课桌记录中的学生id。只需两条update语句即可完成此操作。
https://stackoverflow.com/questions/12689097
复制