4

我有一個使用Tapestry5(java webframework)和Hibernate製作的Web應用程序。現在我試圖添加樂觀鎖定。所以我添加了一個版本屬性和樂觀鎖定工作,所以這很容易和快速。最佳實踐Hibernate樂觀鎖定和Web應用程序

但是,由於我的web應用程序使用「session-per-request」模式,我不確定使用此樂觀鎖定的最佳方式是什麼。

會發生什麼:

用戶A打開頁面,其中已賦值從entityA形式(第1版)。

UserB用加載了entityA(版本1)中的值的表單打開頁面。

UserA更改一些值並提交表單。 - >新請求檢索entityA(版本1)並提交更改(entityA現在爲版本2)

UserB更改一些值並提交表單。 - >新請求檢索entityA(版本2),並承諾改變(entityA現在是第3版)

應該發生用戶B的

的變化不應該犯了什麼。但是由於session-per-request模式,Hibernate發生樂觀鎖定錯誤的時間窗口可能會縮短到提交後的新請求的時間範圍內,這不是所期望的結果。

可能的解決方案

經過一番研究,我發現了以下內容:

  • 隱藏字段添加到窗體與實體版本

我可以用這個值來設置提交之前的實體版本,但Hibernate文檔不建議設置此值。 另外它只在實體分離並重新連接時才起作用,否則手動設置的版本值將被Hibernate忽略。

其次我可以使用這個版本值來做一個手動檢查,如果表單呈現時的版本與提交請求中加載的實體版本相同。然後根據需要自己拋出一個OptimisticLockingException。

  • 將分離的實體到HttpSession中,所以我不必再重新裝上提交

結論

這些方法的工作,但似乎沒有太大的實用我很容易犯錯誤。 所以我想知道其他人是如何實現這個問題的。

回答

1

我最終實現以下:

  • 隱藏字段添加到窗體與實體版本
  • 形式DTO的使用對象
  • 附加這些DTO對象到HttpSession(會話狀態跨越多個請求)
  • dto和實際對象之間的手動版本檢查
0

當您將一個持久實體分離出來以將其轉移到Web層時,例如創建DTO以將對象傳輸到Web層。在這種情況下,我們將使用getter和setter將Entity對象轉換爲DTO對象。

如果您需要使用樂觀鎖定維護併發控制,則必須在應用程序中維護版本號(與手動設置版本號不同)。否則,我們無法指示休眠什麼是舊版本的加載記錄。在hibernate文檔中,它說:「使斷開連接的Session保持接近持久層,使用EJB有狀態會話bean將會話保存在三層環境中,不要將其轉移到Web層,或者將其序列化到單獨的層,將其存儲在HttpSession中。「但是,所有環境都沒有業務層中的EJB有狀態會話bean。在這種情況下,我們必須保持版本號。

只要你可以維護版本,你不需要手動檢查程序中的版本,如果你讓hibernate做到這一點是非常有效的,因爲你無法預測對象層次的深度。

所以你可以做的就是如果你在web層使用分離的對象,你必須再次將版本設置爲持久化實體,然後hibernate將負責Cocurrency控制。

相關問題