熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

開源技術:hiernate的鎖機制

2013-11-23 20:14:41  來源: Java開源技術 
學了兩天的hibernate鎖機制今天寫個總結

hibernate鎖機制包括悲觀鎖和樂觀鎖
悲觀鎖
   它指的是對數據被外界修改持保守態度假定任何時刻存取數據時都可能有另一個客戶也正在

存取同一筆數據為了保持數據被操作的一致性於是對數據采取了數據庫層次的鎖定狀態依靠數

據庫提供的鎖機制來實現

   基於jdbc實現的數據庫加鎖如下
   select * from account where name=Erica for update在更新的過程中數據庫處於加鎖狀

任何其他的針對本條數據的操作都將被延遲本次事務提交後解鎖

   而hibernate悲觀鎖的具體實現如下
   String sql=查詢語句;
   Query query=sessioncreateQuery(sql);
   querysetLockMode(對象LockModelUPGRADE);

   說到這裡就提到了hiernate的加鎖模式
   LockModeNONE  無鎖機制
   LockModeWRITE Hibernate在Insert和Update記錄的時候會自動獲取
   LockModeREAD  Hibernate在讀取記錄的時候會自動獲取
   這三種加鎖模式是供hibernate內部使用的與數據庫加鎖無關
   LockModeUPGRADE利用數據庫的for update字句加鎖
   在這裡我們要注意的是只有在查詢開始之前(也就是hiernate生成sql語句之前)加鎖才會真

正通過數據庫的鎖機制加鎖處理否則數據已經通過不包含for updata子句的sql語句加載進來

所謂的數據庫加鎖也就無從談起

   但是從系統的性能上來考慮對於單機或小系統而言這並不成問題然而如果是在網絡上的

系統同時間會有許多聯機假設有數以百計或上千甚至更多的並發訪問出現我們該怎麼辦?如果

等到數據庫解鎖我們再進行下面的操作我們浪費的資源是多少?這也就導致了樂觀鎖的產生
樂觀鎖
 樂觀鎖定(optimistic locking)則樂觀的認為資料的存取很少發生同時存取的問題因而不作數

據庫層次上的鎖定為了維護正確的數據樂觀鎖定采用應用程序上的邏輯實現版本控制的方法
 例如若有兩個客戶端A客戶先讀取了賬戶余額之後B客戶也讀取了賬戶余額元的數據

A客戶提取了對數據庫作了變更此時數據庫中的余額為B客戶也要提取根據其所

取得的資料將為余額若此時再對數據庫進行變更最後的余額就會不正確
 在不實行悲觀鎖定策略的情況下數據不一致的情況一但發生有幾個解決的方法一種是先更新

為主一種是後更新的為主比較復雜的就是檢查發生變動的數據來實現或是檢查所有屬性來實現

樂觀鎖定
 Hibernate 中透過版本號檢查來實現後更新為主這也是Hibernate所推薦的方式在數據庫中加

入一個VERSON欄記錄在讀取數據時連同版本號一同讀取並在更新數據時遞增版本號然後比對版

本號與數據庫中的版本號如果大於數據庫中的版本號則予以更新否則就回報錯誤
 以剛才的例子A客戶讀取賬戶余額並連帶讀取版本號為的話B客戶此時也讀取賬號余

版本號也為A客戶在領款後賬戶余額為此時將版本號加版本號目前為而數

據庫中版本號為所以予以更新更新數據庫後數據庫此時余額為版本號為B客戶領款後

要變更數據庫其版本號為但是數據庫的版本號為此時不予更新B客戶數據重新讀取數據庫

中新的數據並重新進行業務流程才變更數據庫
 以Hibernate實現版本號控制鎖定的話我們的對象中增加一個version屬性例如

public class Account {

    private int version;

    

 

    public void setVersion(int version) {

        thisversion = version;

    }

 

    public int getVersion() {

        return version;

    }

    

}


而在映像文件中我們使用optimisticlock屬性設定version控制<id>屬性欄之後增加一個

<version>標簽如下

<hibernatemapping>

    <class name=onlyfuncaterpillarAccount talble=ACCOUNT

           optimisticlock=version>

        <id/>

        <version name=version column=VERSION/>

 

         

 

    </class>

</hibernatemapping>


 設定好版本控制之後在上例中如果B 客戶試圖更新數據將會引發StableObjectStateException

例外我們可以捕捉這個例外在處理中重新讀取數據庫中的數據同時將 B客戶目前的數據與數據

庫中的數據秀出來讓B客戶有機會比對不一致的數據以決定要變更的部份或者您可以設計程式

自動讀取新的資料並重復扣款業務流程直到數據可以更新為止這一切可以在背景執行而不用

讓您的客戶知道
   但是樂觀鎖也有不能解決的問題存在上面已經提到過樂觀鎖機制的實現往往基於系統中的數據

存儲邏輯在我們的系統中實現來自外部系統的用戶余額更新不受我們系統的控制有可能造成非

法數據被更新至數據庫因此我們在做電子商務的時候一定要小心的注意這項存在的問題采用比

較合理的邏輯驗證避免數據執行錯誤

 也可以在使用Session的load()或是lock()時指定鎖定模式以進行鎖定
 如果數據庫不支持所指定的鎖定模式Hibernate會選擇一個合適的鎖定替換而不是丟出一個例外
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28182.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.