自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Hibernate樂觀并發(fā)控制

開發(fā) 后端
Hibernate樂觀并發(fā)控制的代碼提供了三種可能的方法,應(yīng)用程序在編寫這些代碼時,可以采用它們。前面應(yīng)用程序?qū)υ捘遣糠终故玖薍ibernate樂觀并發(fā)控制的應(yīng)用場景。

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

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

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

未能充分利用Hibernate功能的實(shí)現(xiàn)代碼中,每次和數(shù)據(jù)庫交互都需要一個新的 Session,而且開發(fā)人員必須在顯示數(shù)據(jù)之前從數(shù)據(jù)庫中重 新載入所有的持久化對象實(shí)例。這種方式迫使應(yīng)用程序自己實(shí)現(xiàn)版本檢查來確保 對話事務(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.  
  5. int oldVersion = foo.getVersion();  
  6. session.load( foo, foo.getKey() ); // load the current state  
  7. if ( oldVersion!=foo.getVersion ) throw new StaleObjectStateException();  
  8. foo.setProperty("bar");  
  9.  
  10. t.commit();  
  11. session.close(); 

version 屬性使用 來映射,如果對象 是臟數(shù)據(jù),在同步的時候,Hibernate會自動增加版本號。

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

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

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

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

在等待用戶交互的時候, Session 斷開底層的JDBC連接。這種方式 以數(shù)據(jù)庫訪問的角度來說是***效的方式。應(yīng)用程序不需要關(guān)心版本檢查或脫管對象實(shí)例 的重新關(guān)聯(lián),在每個數(shù)據(jù)庫事務(wù)中,應(yīng)用程序也不需要載入讀取對象實(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.  
  4. foo.setProperty("bar");  
  5.  
  6. session.flush();    // Only for last transaction in conversation  
  7. t.commit();         // Also return JDBC connection  
  8. session.close();    // Only for last transaction in conversation  

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

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

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

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

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

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

3. 脫管對象(deatched object)和自動版本化

這種方式下,與持久化存儲的每次交互都發(fā)生在一個新的Session中。 然而,同一持久化對象實(shí)例可以在多次與數(shù)據(jù)庫的交互中重用。應(yīng)用程序操縱脫管對象實(shí)例 的狀態(tài),這個脫管對象實(shí)例最初是在另一個Session 中載入的,然后 調(diào)用 Session.update(),Session.saveOrUpdate(), 或者 Session.merge() 來重新關(guān)聯(lián)該對象實(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會再一次在同步的時候檢查對象實(shí)例的版本,如果發(fā)生更新沖突,就拋出異常。

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

4. 定制自動版本化行為

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

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

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

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

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

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

【編輯推薦】

  1. 淺析Hibernate VO與PO區(qū)別
  2. Hibernate中merge()方法解析
  3. Hibernate中Criteria攻略詳解
  4. 簡述Hibernate 3中的XML持久性
  5. 簡述Hibernate三種查詢的應(yīng)用
責(zé)任編輯:仲衡 來源: javanb
相關(guān)推薦

2010-08-18 09:00:38

數(shù)據(jù)庫

2021-01-15 05:12:14

Java并發(fā)樂觀鎖

2009-09-23 10:14:10

Hibernate使用

2009-09-25 16:43:44

Hibernate悲觀Hibernate樂觀

2017-08-21 10:56:55

MySQL并發(fā)控制

2023-10-13 00:00:00

并發(fā)樂觀鎖CAS

2024-06-17 08:40:16

2022-12-12 09:07:06

Redis并發(fā)限流

2012-02-02 15:57:09

HibernateJava

2023-07-05 08:18:54

Atomic類樂觀鎖悲觀鎖

2020-07-06 08:03:32

Java悲觀鎖樂觀鎖

2024-04-30 10:29:46

前端開發(fā)h5開發(fā)函數(shù)

2010-11-08 10:57:05

SQL Server的

2021-01-12 10:22:45

JavaScript并發(fā)控制前端

2021-06-29 23:40:19

Golang語言并發(fā)

2021-04-07 06:00:18

JavaScript 前端并發(fā)控制

2023-11-09 15:28:32

Spring開發(fā)

2017-02-28 17:46:15

Linux驅(qū)動技術(shù)并發(fā)控制

2009-02-09 10:06:03

并發(fā)控制Web應(yīng)用悲觀鎖

2024-08-26 13:23:26

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號