JPA/Hibernate:基於版本的樂觀鎖併發控制

比方說,我們有一個系統由多個用戶使用,其中每個實體可以被多個用戶修改。我們希望避免這種情況:兩個人的加載一些信息,基於他們所看到的做出一些決定,然後在相同的時間。更新狀態,我們不讓讓後一個用戶覆蓋前面一個用戶做出的修改。

  它也可以發生在服務器環境 - 多個事務可以修改共享的實體:

  1. 事務1加載數據
  2. 事務2更新數據,並確認
  3. 事務1基於第一步加載的數據(不是當前最新數據,最新數據已經被事務2修改過),執行某些計算並更新狀態,

  解決辦法使用@Version 如下:

@Entity
@Table(name = 'orders')
public class Order {
       @Id
       private long id;

       @Version
       private int version;

       private String description;

       private String status;

       // ... mutators
}

當這個實體被持久化時,version被設置爲開始值。

只要它被更新,hibernate總是執行:

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

我們結合GUI來看一下執行順序。

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

更新訂單時, version被設置爲2了。而同時另外一個version是1的用戶也開始更新訂單了:

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

這個更新無用,因爲version已經變成了2. Hibernate會發現,拋出: org.hibernate.StaleObjectStateException

第二個用戶看到這種出錯,再也不能操作了,除非重新刷新頁面。獲取最新被修改的值。

優點:

  1. 它提供了一個方便,以自動化的方式來保持一致性,像上述的案例。這意味着,每一個動作只能執行一次,它保證用戶或服務器過程中看到的是最新狀態。
  2. 它需要很少的工作來設置。
  3. 由於其樂觀的天性,速度非常快。沒有鎖定的任何地方,只是多了一個字段添加到查詢中。
發佈了47 篇原創文章 · 獲贊 34 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章