<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    細(xì)心!用心!耐心!

    吾非文人,乃市井一俗人也,讀百卷書(shū),跨江河千里,故申城一游; 一兩滴辛酸,三四年學(xué)業(yè),五六點(diǎn)粗墨,七八筆買(mǎi)賣(mài),九十道人情。

    BlogJava 聯(lián)系 聚合 管理
      1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks
    Hibernate支持兩種鎖機(jī)制:
    即通常所說(shuō)的“悲觀鎖(Pessimistic Locking)”和 “樂(lè)觀鎖(OptimisticLocking)”。

    悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫(kù)提供的鎖機(jī)制(也只有數(shù)據(jù)庫(kù)層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問(wèn)的排他性,否則,即使在本系統(tǒng)中實(shí)現(xiàn)了加鎖機(jī)制,也無(wú)法保證外部系統(tǒng)不會(huì)修改數(shù)據(jù))。

    Hibernate的加鎖模式有:
    Ø LockMode.NONE : 無(wú)鎖機(jī)制。
    Ø LockMode.WRITE :Hibernate在Insert和Update記錄的時(shí)候會(huì)自動(dòng)
    獲取。
    Ø LockMode.READ : Hibernate在讀取記錄的時(shí)候會(huì)自動(dòng)獲取。
    以上這三種鎖機(jī)制一般由Hibernate內(nèi)部使用,如Hibernate為了保證Update
    過(guò)程中對(duì)象不會(huì)被外界修改,會(huì)在save方法實(shí)現(xiàn)中自動(dòng)為目標(biāo)對(duì)象加上WRITE鎖。
    Ø LockMode.UPGRADE :利用數(shù)據(jù)庫(kù)的for update子句加鎖。
    Ø LockMode. UPGRADE_NOWAIT :Oracle的特定實(shí)現(xiàn),利用Oracle的for update nowait子句實(shí)現(xiàn)加鎖。 

     Hibernate的悲觀鎖,也是基于數(shù)據(jù)庫(kù)的鎖機(jī)制實(shí)現(xiàn)。 下面的代碼實(shí)現(xiàn)了對(duì)查詢(xún)記錄的加鎖:
    1 String hqlStr  =   " from TUser as user where user.name=’Erica’ "
    2 Query query  =  session.createQuery(hqlStr); 
    3 query.setLockMode( " user " ,LockMode.UPGRADE);  // 加鎖 
    4 List userList  =  query.list(); // 執(zhí)行查詢(xún),

    獲取數(shù)據(jù) query.setLockMode 對(duì)查詢(xún)語(yǔ)句中特定別名所對(duì)應(yīng)的記錄進(jìn)行加鎖(我們?yōu)?TUser類(lèi)指定了一個(gè)別名“user”),這里也就是對(duì)返回的所有user記錄進(jìn)行加鎖。 觀察運(yùn)行期Hibernate生成的SQL語(yǔ)句: 

    1 select tuser0_.id as id, tuser0_.name as name, tuser0_.group_id as group_id, tuser0_.user_type as user_type, tuser0_.sex as sex from t_user tuser0_ where (tuser0_.name = ’Erica’ )  for  update

     這里Hibernate通過(guò)使用數(shù)據(jù)庫(kù)的for update子句實(shí)現(xiàn)了悲觀鎖機(jī)制。

    上面這兩種鎖機(jī)制是我們?cè)趹?yīng)用層較為常用的,加鎖一般通過(guò)以下方法實(shí)現(xiàn):
    Criteria.setLockMode
    Query.setLockMode
    Session.lock
    注意,只有在查詢(xún)開(kāi)始之前(也就是Hiberate 生成SQL 之前)設(shè)定加鎖,才會(huì) 真正通過(guò)數(shù)據(jù)庫(kù)的鎖機(jī)制進(jìn)行加鎖處理,否則,數(shù)據(jù)已經(jīng)通過(guò)不包含for update 子句的Select SQL加載進(jìn)來(lái),所謂數(shù)據(jù)庫(kù)加鎖也就無(wú)從談起。






    樂(lè)觀鎖,大多是基于數(shù)據(jù)版本(Version)記錄機(jī)制實(shí)現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí),在基于數(shù)據(jù)庫(kù)表的版本解決方案中,一般是通過(guò)為數(shù)據(jù)庫(kù)表增加一個(gè)“version”字段來(lái)實(shí)現(xiàn)。讀取出數(shù)據(jù)時(shí),將此版本號(hào)一同讀出,之后更新時(shí),對(duì)此版本號(hào)加一。此時(shí),將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對(duì),如果提交的數(shù)據(jù)版本號(hào)大于數(shù)據(jù)庫(kù)表當(dāng)前版本號(hào),則予以更新,否則認(rèn)為是過(guò)期數(shù)據(jù)。

    1. 首先為T(mén)User的class描述符添加optimistic-lock屬性:
    < hibernate - mapping >  
    < class  
    name
    = " org.hibernate.sample.TUser "  
    table
    = " t_user "  
    dynamic
    - update = " true "  
    dynamic
    - insert = " true "  
    optimistic
    - lock = " version "  
    >  
    …… 
    </ class >  
    </ hibernate - mapping >  

     

     添加一個(gè)Version屬性描述符
    代碼內(nèi)容
     1 < hibernate - mapping >   
     2 < class   
     3 name = " org.hibernate.sample.TUser "   
     4 table = " t_user "   
     5 dynamic - update = " true "   
     6 dynamic - insert = " true "   
     7 optimistic - lock = " version "   
     8 >   
     9 < id  
    10 name = " id "   
    11 column = " id "   
    12 type = " java.lang.Integer "   
    13 >   
    14 < generator  class = " native " >   
    15 </ generator >   
    16 </ id >   
    17 < version  
    18 column = " version "   
    19 name = " version "   
    20 type = " java.lang.Integer "   
    21 />   
    22 ……  
    23 </ class >   
    24 </ hibernate - mapping >   
    25


     


    注意version 節(jié)點(diǎn)必須出現(xiàn)在ID 節(jié)點(diǎn)之后。
     這里我們聲明了一個(gè)version屬性,用于存放用戶(hù)的版本信息,保存在TUser表的 version字段中。 此時(shí)如果我們嘗試編寫(xiě)一段代碼,更新TUser表中記錄數(shù)據(jù),如:
    代碼內(nèi)容

    1 Criteria criteria  =  session.createCriteria(TUser. class );  
    2 criteria.add(Expression.eq( " name " , " Erica " ));  
    3 List userList  =  criteria.list();  
    4 TUser user  = (TUser)userList.get( 0 );  
    5 Transaction tx  =  session.beginTransaction();  
    6 user.setUserType( 1 );  // 更新UserType字段  
    7 tx.commit();  
    8

    每次對(duì)TUser進(jìn)行更新的時(shí)候,我們可以發(fā)現(xiàn),數(shù)據(jù)庫(kù)中的version都在遞增。 而如果我們嘗試在tx.commit 之前,啟動(dòng)另外一個(gè)Session,對(duì)名為Erica 的用 戶(hù)進(jìn)行操作,以模擬并發(fā)更新時(shí)的情形:
    代碼內(nèi)容

     1 Session session =  getSession();  
     2 Criteria criteria  =  session.createCriteria(TUser. class );  
     3 criteria.add(Expression.eq( " name " , " Erica " ));  
     4 Session session2  =  getSession();  
     5 Criteria criteria2  =  session2.createCriteria(TUser. class );  
     6 criteria2.add(Expression.eq( " name " , " Erica " ));  
     7 List userList  =  criteria.list();  
     8 List userList2  =  criteria2.list();TUser user  = (TUser)userList.get( 0 );  
     9 TUser user2  = (TUser)userList2.get( 0 );  
    10 Transaction tx  =  session.beginTransaction();  
    11 Transaction tx2  =  session2.beginTransaction();  
    12 user2.setUserType( 99 );  
    13 tx2.commit();  
    14 user.setUserType( 1 );  
    15 tx.commit();  
    16

    執(zhí)行以上代碼,代碼將在tx.commit()處拋出StaleObjectStateException異 常,并指出版本檢查失敗,當(dāng)前事務(wù)正在試圖提交一個(gè)過(guò)期數(shù)據(jù)。通過(guò)捕捉這個(gè)異常,我 們就可以在樂(lè)觀鎖校驗(yàn)失敗時(shí)進(jìn)行相應(yīng)處理。 




    悲觀鎖與樂(lè)觀鎖的比較:
    悲觀鎖大多數(shù)情況下依靠數(shù)據(jù)庫(kù)的鎖機(jī)制實(shí)現(xiàn),以保證操作最大程度的獨(dú)占性。但隨之而來(lái)的就是數(shù)據(jù)庫(kù)性能的大量開(kāi)銷(xiāo),特別是對(duì)長(zhǎng)事務(wù)而言,這樣的開(kāi)銷(xiāo)往往無(wú)法承受;
    相對(duì)悲觀鎖而言,樂(lè)觀鎖機(jī)制采取了更加寬松的加鎖機(jī)制。樂(lè)觀鎖機(jī)制往往基于系統(tǒng)中的數(shù)據(jù)存儲(chǔ)邏輯,因此也具備一定的局限性,如在上例中,由于樂(lè)觀鎖機(jī)制是在我們的系統(tǒng)中實(shí)現(xiàn),來(lái)自外部系統(tǒng)的更新操作不受我們系統(tǒng)的控制,因此可能會(huì)造成臟數(shù)據(jù)被更新到數(shù)據(jù)庫(kù)中。在
    系統(tǒng)設(shè)計(jì)階段,我們應(yīng)該充分考慮到這些情況出現(xiàn)的可能性,并進(jìn)行相應(yīng)調(diào)整(如將樂(lè)觀鎖策略在數(shù)據(jù)庫(kù)存儲(chǔ)過(guò)程中實(shí)現(xiàn),對(duì)外只開(kāi)放基于此存儲(chǔ)過(guò)程的數(shù)據(jù)更新途徑,而不是將數(shù)據(jù)庫(kù)表直接對(duì)外公開(kāi))。
    Hibernate 在其數(shù)據(jù)訪問(wèn)引擎中內(nèi)置了樂(lè)觀鎖實(shí)現(xiàn)。如果不用考慮外部系統(tǒng)對(duì)數(shù)據(jù)庫(kù)的更新操作,利用Hibernate提供的透明化樂(lè)觀鎖實(shí)現(xiàn),將大大提升我們的生產(chǎn)力。
    Hibernate中可以通過(guò)class描述符的optimistic-lock屬性結(jié)合version描述符指定。
    optimistic-lock屬性有如下可選取值:
    Ø none
    無(wú)樂(lè)觀鎖
    Ø version
    通過(guò)版本機(jī)制實(shí)現(xiàn)樂(lè)觀鎖
    Ø dirty
    通過(guò)檢查發(fā)生變動(dòng)過(guò)的屬性實(shí)現(xiàn)樂(lè)觀鎖
    Ø all
    通過(guò)檢查所有屬性實(shí)現(xiàn)樂(lè)觀鎖
    其中通過(guò)version實(shí)現(xiàn)的樂(lè)觀鎖機(jī)制是Hibernate官方推薦的樂(lè)觀鎖實(shí)現(xiàn),同時(shí)也是Hibernate中,目前唯一在數(shù)據(jù)對(duì)象脫離Session發(fā)生修改的情況下依然有效的鎖機(jī)制。因此,一般情況下,我們都選擇version方式作為Hibernate樂(lè)觀鎖實(shí)現(xiàn)機(jī)制。
    posted on 2012-10-11 10:56 張金鵬 閱讀(151) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲AV无码专区在线亚| 中文字幕中韩乱码亚洲大片 | 日批日出水久久亚洲精品tv| 亚洲精品午夜国产VA久久成人| 亚洲风情亚Aⅴ在线发布| 免费视频淫片aa毛片| 亚洲一级毛片在线观| 免费观看成人毛片a片2008| 久久亚洲国产成人影院| 在线免费不卡视频| 国产亚洲精品AAAA片APP| 九月婷婷亚洲综合在线| 一级**爱片免费视频| 国产V亚洲V天堂无码久久久| 日本免费高清视频| 亚洲精品影院久久久久久| 很黄很色很刺激的视频免费| 精品亚洲AV无码一区二区| 国产18禁黄网站免费观看| av片在线观看永久免费| 午夜亚洲www湿好大| 无人在线直播免费观看| 久久精品熟女亚洲av麻豆| 国产亚洲精久久久久久无码AV| 三级网站免费观看| 亚洲国产中文在线二区三区免| 女人被男人躁的女爽免费视频 | 中文字幕在线视频免费观看 | 亚洲gv白嫩小受在线观看| 在线观看免费av网站| 亚洲一卡一卡二新区无人区| 免费a级毛片无码av| 中文字幕乱码一区二区免费| 亚洲精品国产情侣av在线| 国产网站在线免费观看| 国产免费网站看v片在线| 国产亚洲中文日本不卡二区| 中文字幕一精品亚洲无线一区| 日本免费xxxx| 一级做a爰性色毛片免费| 亚洲日韩国产精品无码av|