2012-10-02 125 views
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關係」 –