日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JPA / Hibernate:基于版本的乐观并发控制

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JPA / Hibernate:基于版本的乐观并发控制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文是Hibernate和JPA中基于版本的樂觀并發控制的簡介。 這個概念已經很老了,上面已經寫了很多東西,但是無論如何我都看到了它被重新發明,誤解和濫用。 我在編寫它只是為了傳播知識,并希望引起人們對并發控制和鎖定的興趣。

用例

假設我們有一個供多個用戶使用的系統,其中每個實體可以由多個用戶修改。 我們希望避免兩個人加載一些信息,根據他們看到的內容做出一些決定并同時更新狀態的情況。 我們不希望丟失在第一個交易中首先單擊“保存”的用戶通過覆蓋它們所做的更改。

它也可能在服務器環境中發生–多個事務可以修改共享實體,我們希望避免出現以下情況:

  • 交易1載入資料
  • 事務2更新該數據并提交
  • 使用在步驟1中加載的狀態(不再是當前狀態),事務1執行一些計算并更新狀態
  • 在某些方面,它與不可重復的讀取具有可比性。

    解決方案:版本控制

    因此,Hibernate和JPA實現了基于版本的并發控制的概念。 運作方式如下。

    您可以使用@Version或<version> (數字或時間戳)標記一個簡單的屬性。 這將是數據庫中的特殊列。 我們的映射如下所示:

    @Entity @Table(name = 'orders') public class Order {@Idprivate long id;@Versionprivate int version;private String description;private String status;// ... mutators }

    當這樣的實體持續存在時,version屬性將設置為起始值。

    每當更新時,Hibernate都會執行如下查詢:

    update orders set description=?, status=?, version=? where id=? and version=?

    請注意,在最后一行, WHERE子句現在包括version 。 此值始終設置為“舊”值,因此只有在具有預期版本的情況下,它才會更新行。

    假設有兩個用戶在版本1中加載訂單,并花一些時間在GUI中查看訂單。

    安妮決定批準該訂單并執行該操作。 數據庫中的狀態已更新,一切正常。 傳遞給update語句的版本如下:

    update orders set description=?, status=?, version=2 where id=? and version=1

    如您所見,在持久化更新持久層時,版本計數器將增加到2。

    在她的GUI中,Betty仍然具有舊版本(編號1)。 當她決定對訂單執行更新時,該語句如下所示:

    update orders set description=?, status=?, version=2 where id=? and version=1

    此時,在Anne的更新之后,數據庫中該行的版本為2。因此,第二次更新影響0行(沒有與WHERE子句匹配的行)。 Hibernate會檢測到它,并檢測到一個org.hibernate.StaleObjectStateException (包裝在javax.persistence.OptimisticLockException )。

    結果,第二個用戶除非刷新視圖,否則無法執行任何更新。 為了獲得適當的用戶體驗,我們需要進行一些干凈的異常處理,但是我將省略。

    組態

    這里幾乎沒有要自定義的內容。 @Version屬性可以是數字或時間戳。 數字是人為的,但通常在內存和數據庫中占用較少的字節。 時間戳較大,但始終會更新為“當前時間戳”,因此您可以實際使用它來確定實體的更新時間。

    為什么?

    那為什么要使用它呢?

    • 它提供了一種方便且自動化的方式來維持上述情況下的一致性。 這意味著每個動作只能執行一次,并且可以確保用戶或服務器進程在制定業務決策時看到最新狀態。
    • 設置只需很少的工作。
    • 由于其樂觀的性質,因此速度很快。 在任何地方都沒有鎖定,只有一個字段添加到同一查詢中。
    • 在某種程度上,即使在已提交讀事務隔離級別的情況下,它也可以確保可重復讀。 它將以一個異常結束,但是至少不可能創建不一致的狀態。
    • 它適用于非常長的對話,包括跨越多個事務的對話。
    • 在ACID數據庫上的所有可能情況和競爭條件下,它都是完全一致的。 更新必須是順序更新,更新涉及行鎖定,而“第二”更新將始終影響0行并失敗。


    演示版

    為了演示這一點,我創建了一個非常簡單的Web應用程序。 它將Spring和Hibernate連接在一起(在JPA API后面),但是它也可以在其他設置中工作:Pure Hibernate(無JPA),具有不同實現的JPA,非webapp,非Spring等。

    該應用程序保留一個具有與上述類似的架構的Order ,并以Web表單顯示該Order ,您可以在其中更新描述和狀態。 要嘗試并發控制,請在兩個選項卡中打開頁面,進行不同的修改并保存。 不使用@Version嘗試相同的@Version 。

    它使用嵌入式數據庫,因此需要最少的設置(僅Web容器),并且只需重新啟動即可從新數據庫開始。

    這非常簡單-在@Transactional @Controller訪問EntityManager并直接使用JPA映射的實體支持表單。 對于不太瑣碎的項目而言,這可能不是最好的處理方法,但是至少它將所有代碼集中在一個地方并且非常容易掌握。

    可以在我的GitHub存儲庫中找到Eclipse項目的完整源代碼。

    參考: 在我們的JCG合作伙伴 Konrad Garus的Squirrel博客上,JPA / Hibernate中基于版本的樂觀并發控制 。

    翻譯自: https://www.javacodegeeks.com/2012/11/jpahibernate-version-based-optimistic-concurrency-control.html

    總結

    以上是生活随笔為你收集整理的JPA / Hibernate:基于版本的乐观并发控制的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。