0

我想更新一个Java实体的集合,但Hibernate执行批量更新的顺序导致违反约束的异常。 我将使用下面的例子来解释这种情况。休眠批量更新

实体学生 诠释ID 字符串名称 字符串deskID

规则:2个学生不能有相同的办公桌

月1日的交易:将2名学生如下 学生1 ID:1 名称: ABC DeskId:D1

学生2 ID:2 名称:DEF DeskId:D2

现在,在这之后,我决定同时更新学生的实体来交换自己的办公桌 我发送更新的学生实体的集合冬眠更新 学生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; 

回答

1

你的问题的根源是清楚的:当执行SQL语句,而不是在提交时的数据库检查的约束。在执行第一个SQL语句时违反了约束。

当您先从学生1中取出桌子,然后将其分配给学生2,然后给学生1递交其说明时,您可以解决问题。这意味着三条SQL语句(超过必要的一条),然后在每次更新后(或者重新排序SQL语句,这可能会干扰您的手动订单),您可能需要刷新会话。

但更好的解决方案是纠正您的数据模型中的问题。

如果每个办公桌只能由一个学生所有,那么从办公桌到学生就有一个n:1的关系。办公桌需要学生的ID作为外键。不需要定义额外的约束。现在更改桌面意味着更改桌面记录中的学生ID。这只能用两个更新语句来完成。

+0

感谢您的回复,实际上我的数据模型比这更复杂。一个很好的例子来表示我的问题将是..学生有2个属性开始日期和结束日期,我对数据库有一个约束,说没有2名学生应该有重叠的开始和结束日期...这意味着我们不能有开始日期为1和结束日期为4的学生以及开始日期为2和结束日期为6 – Priyam

+0

的另一名学生同意建议“从桌面到学生的n:1关系” –