日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Hibernate樂觀并發(fā)控制

Hibernate樂觀并發(fā)控制(Optimistic concurrency control)唯一能夠同時(shí)保持高并發(fā)和高可伸縮性的方法就是使用帶版本化的Hibernate樂觀并發(fā)控制。版本檢查使用版本號(hào)、 或者時(shí)間戳來檢測(cè)更新沖突(并且防止更新丟失)。

Hibernate樂觀并發(fā)控制的代碼提供了三種可能的方法,應(yīng)用程序在編寫這些代碼時(shí),可以采用它們。我們已經(jīng)在前面應(yīng)用程序?qū)υ捘遣糠终故玖藰酚^并發(fā)控制的應(yīng)用場(chǎng)景,此外,在單個(gè)數(shù)據(jù)庫(kù)事務(wù)范圍內(nèi),版本檢查也提供了防止更新丟失的好處。

1. 應(yīng)用程序級(jí)別的版本檢查(Application version checking)

未能充分利用Hibernate功能的實(shí)現(xiàn)代碼中,每次和數(shù)據(jù)庫(kù)交互都需要一個(gè)新的 Session,而且開發(fā)人員必須在顯示數(shù)據(jù)之前從數(shù)據(jù)庫(kù)中重 新載入所有的持久化對(duì)象實(shí)例。這種方式迫使應(yīng)用程序自己實(shí)現(xiàn)版本檢查來確保 對(duì)話事務(wù)的隔離,從數(shù)據(jù)訪問的角度來說是***效的。這種使用方式和 entity EJB最相似。

 
 
 
  1. // foo is an instance loaded by a previous Session
  2. session = factory.openSession();
  3. Transaction t = session.beginTransaction();
  4. int oldVersion = foo.getVersion();
  5. session.load( foo, foo.getKey() ); // load the current state
  6. if ( oldVersion!=foo.getVersion ) throw new StaleObjectStateException();
  7. foo.setProperty("bar");
  8. t.commit();
  9. session.close();

version 屬性使用 來映射,如果對(duì)象 是臟數(shù)據(jù),在同步的時(shí)候,Hibernate會(huì)自動(dòng)增加版本號(hào)。

當(dāng)然,如果你的應(yīng)用是在一個(gè)低數(shù)據(jù)并發(fā)環(huán)境下,并不需要版本檢查的話,你照樣可以使用 這種方式,只不過跳過版本檢查就是了。在這種情況下,最晚提交生效 (last commit wins)就是你的長(zhǎng)對(duì)話的默認(rèn)處理策略。 請(qǐng)記住這種策略可能會(huì)讓應(yīng)用軟件的用戶感到困惑,因?yàn)樗麄冇锌赡軙?huì)碰上更新丟失掉卻沒 有出錯(cuò)信息,或者需要合并更改沖突的情況。

很明顯,手工進(jìn)行版本檢查只適合于某些軟件規(guī)模非常小的應(yīng)用場(chǎng)景,對(duì)于大多數(shù)軟件應(yīng)用場(chǎng)景 來說并不現(xiàn)實(shí)。通常情況下,不僅是單個(gè)對(duì)象實(shí)例需要進(jìn)行版本檢查,整個(gè)被修改過的關(guān) 聯(lián)對(duì)象圖也都需要進(jìn)行版本檢查。作為標(biāo)準(zhǔn)設(shè)計(jì)范例,Hibernate使用擴(kuò)展周期的 Session的方式,或者脫管對(duì)象實(shí)例的方式來提供自動(dòng)版本檢查。

2. 擴(kuò)展周期的session和自動(dòng)版本化

單個(gè) Session實(shí)例和它所關(guān)聯(lián)的所有持久化對(duì)象實(shí)例都被用于整個(gè) 對(duì)話,這被稱為session-per-conversation。Hibernate在同步的時(shí)候進(jìn)行對(duì)象實(shí)例的版本檢查,如果檢測(cè)到并發(fā)修 改則拋出異常。由開發(fā)人員來決定是否需要捕獲和處理這個(gè)異常(通常的抉擇是給用戶 提供一個(gè)合并更改,或者在無臟數(shù)據(jù)情況下重新進(jìn)行業(yè)務(wù)對(duì)話的機(jī)會(huì))。

在等待用戶交互的時(shí)候, Session 斷開底層的JDBC連接。這種方式 以數(shù)據(jù)庫(kù)訪問的角度來說是***效的方式。應(yīng)用程序不需要關(guān)心版本檢查或脫管對(duì)象實(shí)例 的重新關(guān)聯(lián),在每個(gè)數(shù)據(jù)庫(kù)事務(wù)中,應(yīng)用程序也不需要載入讀取對(duì)象實(shí)例。

 
 
 
  1. // foo is an instance loaded earlier by the old session
  2. Transaction t = session.beginTransaction(); // Obtain a new JDBC connection, start transaction
  3. foo.setProperty("bar");
  4. session.flush();    // Only for last transaction in conversation
  5. t.commit();         // Also return JDBC connection
  6. session.close();    // Only for last transaction in conversation

foo對(duì)象知道它是在哪個(gè)Session中被裝入的。在一個(gè)舊session中開啟一個(gè)新的數(shù)據(jù)庫(kù)事務(wù),會(huì)導(dǎo)致session獲取一個(gè)新的連接,并恢復(fù)session的功能。將數(shù)據(jù)庫(kù)事務(wù)提交,使得session從JDBC連接斷開,并將此連接交還給連接池。在重新連接之后,要強(qiáng)制對(duì)你沒有更新的數(shù)據(jù)進(jìn)行一次版本檢查,你可以對(duì)所有可能被其他事務(wù)修改過的對(duì)象,使用參數(shù)LockMode.READ來調(diào)用Session.lock()。你不用lock任何你正在更新的數(shù)據(jù)。

一般你會(huì)在擴(kuò)展的Session上設(shè)置FlushMode.NEVER,因此只有***一個(gè)數(shù)據(jù)庫(kù)事務(wù)循環(huán)才會(huì)真正的吧整個(gè)對(duì)話中發(fā)生的修改發(fā)送到數(shù)據(jù)庫(kù)。因此,只有這***一次數(shù)據(jù)庫(kù)事務(wù)才會(huì)包含flush()操作,然后在整個(gè)對(duì)話結(jié)束后,還要close()這個(gè)session。

如果在用戶思考的過程中,Session因?yàn)樘罅硕荒鼙4?,那么這種模式是有 問題的。舉例來說,一個(gè)HttpSession應(yīng)該盡可能的小。由于 Session是一級(jí)緩存,并且保持了所有被載入過的對(duì)象,因此 我們只應(yīng)該在那些少量的request/response情況下使用這種策略。你應(yīng)該只把一個(gè)Session用于單個(gè)對(duì)話,因?yàn)樗芸炀蜁?huì)出現(xiàn)臟數(shù)據(jù)。

(注意,早期的Hibernate版本需要明確的對(duì)Session進(jìn)行disconnec和reconnect。這些方法現(xiàn)在已經(jīng)過時(shí)了,打開事務(wù)和關(guān)閉事務(wù)會(huì)起到同樣的效果。)

此外,也請(qǐng)注意,你應(yīng)該讓與數(shù)據(jù)庫(kù)連接斷開的Session對(duì)持久層保持 關(guān)閉狀態(tài)。換句話說,在三層環(huán)境中,使用有狀態(tài)的EJB session bean來持有Session, 而不要把它傳遞到web層(甚至把它序列化到一個(gè)單獨(dú)的層),保存在HttpSession中。

擴(kuò)展session模式,或者被稱為每次對(duì)話一個(gè)session(session-per-conversation), 在與自動(dòng)管理當(dāng)前session上下文聯(lián)用的時(shí)候會(huì)更困難。你需要提供你自己的CurrentSessionContext實(shí)現(xiàn)。請(qǐng)參閱Hibernate Wiki以獲得示例。

3. 脫管對(duì)象(deatched object)和自動(dòng)版本化

這種方式下,與持久化存儲(chǔ)的每次交互都發(fā)生在一個(gè)新的Session中。 然而,同一持久化對(duì)象實(shí)例可以在多次與數(shù)據(jù)庫(kù)的交互中重用。應(yīng)用程序操縱脫管對(duì)象實(shí)例 的狀態(tài),這個(gè)脫管對(duì)象實(shí)例最初是在另一個(gè)Session 中載入的,然后 調(diào)用 Session.update(),Session.saveOrUpdate(), 或者 Session.merge() 來重新關(guān)聯(lián)該對(duì)象實(shí)例。

 
 
 
  1. // foo is an instance loaded by a previous Session
  2. foo.setProperty("bar");
  3. session = factory.openSession();
  4. Transaction t = session.beginTransaction();
  5. session.saveOrUpdate(foo); // Use merge() if "foo" might have been loaded already
  6. t.commit();
  7. session.close();

Hibernate會(huì)再一次在同步的時(shí)候檢查對(duì)象實(shí)例的版本,如果發(fā)生更新沖突,就拋出異常。

如果你確信對(duì)象沒有被修改過,你也可以調(diào)用lock() 來設(shè)置 LockMode.READ(繞過所有的緩存,執(zhí)行版本檢查),從而取 代 update()操作。

4. 定制自動(dòng)版本化行為

對(duì)于特定的屬性和集合,通過為它們?cè)O(shè)置映射屬性optimistic-lock的值 為false,來禁止Hibernate的版本自動(dòng)增加。這樣的話,如果該屬性 臟數(shù)據(jù),Hibernate將不再增加版本號(hào)。

遺留系統(tǒng)的數(shù)據(jù)庫(kù)Schema通常是靜態(tài)的,不可修改的?;蛘撸渌麘?yīng)用程序也可能訪問同一數(shù)據(jù) 庫(kù),根本無法得知如何處理版本號(hào),甚至?xí)r間戳。在以上的所有場(chǎng)景中,實(shí)現(xiàn)版本化不能依靠 數(shù)據(jù)庫(kù)表的某個(gè)特定列。在 的映射中設(shè)置 optimistic-lock="all"可以在沒有版本或者時(shí)間戳屬性映射的情況下實(shí)現(xiàn) 版本檢查,此時(shí)Hibernate將比較一行記錄的每個(gè)字段的狀態(tài)。請(qǐng)注意,只有當(dāng)Hibernate能夠比 較新舊狀態(tài)的情況下,這種方式才能生效,也就是說, 你必須使用單個(gè)長(zhǎng)生命周期Session模式,而不能使用 session-per-request-with-detached-objects模式。

有些情況下,只要更改不發(fā)生交錯(cuò),并發(fā)修改也是允許的。當(dāng)你在 的映射中設(shè)置optimistic-lock="dirty",Hibernate在同步的時(shí)候?qū)⒅槐容^有臟 數(shù)據(jù)的字段。

在以上所有場(chǎng)景中,不管是專門設(shè)置一個(gè)版本/時(shí)間戳列,還是進(jìn)行全部字段/臟數(shù)據(jù)字段比較, Hibernate都會(huì)針對(duì)每個(gè)實(shí)體對(duì)象發(fā)送一條UPDATE(帶有相應(yīng)的 WHERE語句 )的SQL語句來執(zhí)行版本檢查和數(shù)據(jù)更新。如果你對(duì)關(guān)聯(lián)實(shí)體 設(shè)置級(jí)聯(lián)關(guān)系使用傳播性持久化(transitive persistence),那么Hibernate可能會(huì)執(zhí)行不必 要的update語句。這通常不是個(gè)問題,但是數(shù)據(jù)庫(kù)里面對(duì)on update點(diǎn)火 的觸發(fā)器可能在脫管對(duì)象沒有任何更改的情況下被觸發(fā)。

因此,你可以在 的映射中,通過設(shè)置select-before-update="true" 來定制這一行為,強(qiáng)制Hibernate SELECT這個(gè)對(duì)象實(shí)例,從而保證, 在更新記錄之前,對(duì)象的確是被修改過。

以上就是對(duì)Hibernate樂觀并發(fā)控制的理解與分析。


網(wǎng)站名稱:Hibernate樂觀并發(fā)控制
鏈接分享:http://www.dlmjj.cn/article/dhojhoe.html