Hibernate樂觀鎖與悲觀鎖

1.悲觀鎖
一個事務訪問某數據庫中一定量的數據時,鎖死這些數據,在commit()釋放鎖前禁止其他線程的任何操作。Hibernate總是使用數據庫的鎖定機制,從不在內存中鎖定對象!
必然發送的sql:for update.
例如:select * from Emp for update.鎖死了Emp表的數據
使用Hibernate設置數據庫隔離級別以實現悲觀鎖:
在Hibernate的配置文件中可以顯示的配置數據庫事務隔離級別。每一個隔離級別用一個整數表示:
8 - Serializable 串行化
4 - Repeatable Read 可重複讀
2 - Read Commited 可讀已提交
1 - Read Uncommited 可讀未提交
參考:https://blog.csdn.net/oLengYueHun/article/details/88641215
在hibernate.cfg.xml中使用hibernate.connection.isolation參數配置數據庫事務隔離級別。

<property name="connection.isolation">8</property>

通常情況下,只要爲 JDBC 連接指定一下隔離級別,然後讓數據庫去搞定一切就夠了,。然而,高級用戶有時候希望進行一個排它的悲觀鎖定,或者在一個新的事務啓動的時候,重新進行鎖定。
類 LockMode 定義了 Hibernate 所需的不同的鎖定級別。一個鎖定可以通過以下的機制來設置:
•當 Hibernate 更新或者插入一行記錄的時候,鎖定級別自動設置爲 LockMode.WRITE。
•當用戶顯式的使用數據庫支持的 SQL 格式 SELECT … FOR UPDATE 發送 SQL 的時候,鎖定級別設置爲 LockMode.UPGRADE。
•當用戶顯式的使用 Oracle 數據庫的 SQL 語句 SELECT … FOR UPDATE NOWAIT 的時候,鎖定級別設置 LockMode.UPGRADE_NOWAIT。
•當 Hibernate 在“可重複讀”或者是“序列化”數據庫隔離級別下讀取數據的時候,鎖定模式
自動設置爲 LockMode.READ。這種模式也可以通過用戶顯式指定進行設置。
•LockMode.NONE 代表無需鎖定。在 Transaction 結束時, 所有的對象都切換到該模式上來。與
session 相關聯的對象通過調用 update() 或者 saveOrUpdate() 脫離該模式。
"顯式的用戶指定"可以通過以下幾種方式之一來表示:
•調用 Session.load() 的時候指定鎖定模式(LockMode)。
例:

session.load(theClass, id, lockMode);//3.6以上hibernate不建議使用load
session.load(entityName, id, lockMode);//3.6以上hibernate不建議使用load
session.get(clazz, id, lockMode);
session.get(clazz, id, lockOptions);

•調用 Session.lock()。
•調用 Query.setLockMode()。
執行代碼後,每個發送的sql都是附有for sql以實現悲觀鎖

2.樂觀鎖:
悲觀鎖大多數情況下依靠數據庫的鎖機制實現,以保證操作最大程度的獨佔性。但隨之而來的就是數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基於數據版本(Version)記錄機制實現。何謂數據版本?即爲數據增加一個版本標識,在基於數據庫表的版本解決方案中,一般是通過爲數據庫表增加一個"version"字段來實現。
  樂觀鎖的工作原理:讀取出數據時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大於數據庫表當前版本號,則予以更新,否則認爲是過期數據。
hibernate設置樂觀鎖:
第一種方法:
1.在對象中:

private int version;
//添加setter和getter

2.設置對象配置文件
在id字段後面設置:

然後就可以了。
注意:1.version必須寫在id後面 2.數據庫的version不能手動去操作或者不能手動去設置setVersion 否則樂觀鎖失效

第二種方法:
1.在對象中設置

private Timestamp timestamp;  //java.sql.Timestamp

2.設置對象配置文件

<timestamp name="timestamp" column="timestamp"></timestamp>

3.第三種方法:
這種方法主要是用在老項目添加樂觀鎖
在對象配置文件(class標籤)上設置

optimistic-lock = true

小結:

樂觀鎖和悲觀鎖區別:
1.樂觀鎖主要藉助於version
2.悲觀鎖主要藉助於數據庫鎖

使用悲觀鎖時,會悲觀鎖定當前數據或對象,在當前事務操作完成之前,其它人無法對這些數據進行操作。
//相當於select * from t_user for update
設置 session.load(studnet,1,LockMode.UPGRADE); 在hibernate3.6之前可以進行悲觀鎖定

使用樂觀鎖參照前面的3種設置方法,只要當前versionid一直就沒問題,如果有且併發有一個version提交version+1;如果併發
發現兩個version不一致就會拋出異常
參考資料:https://download.csdn.net/download/olengyuehun/11082672

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章