成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Hibernate樂觀并發控制

開發 后端
Hibernate樂觀并發控制的代碼提供了三種可能的方法,應用程序在編寫這些代碼時,可以采用它們。前面應用程序對話那部分展示了Hibernate樂觀并發控制的應用場景。

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

Hibernate樂觀并發控制的代碼提供了三種可能的方法,應用程序在編寫這些代碼時,可以采用它們。我們已經在前面應用程序對話那部分展示了樂觀并發控制的應用場景,此外,在單個數據庫事務范圍內,版本檢查也提供了防止更新丟失的好處。

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

未能充分利用Hibernate功能的實現代碼中,每次和數據庫交互都需要一個新的 Session,而且開發人員必須在顯示數據之前從數據庫中重 新載入所有的持久化對象實例。這種方式迫使應用程序自己實現版本檢查來確保 對話事務的隔離,從數據訪問的角度來說是***效的。這種使用方式和 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 屬性使用 來映射,如果對象 是臟數據,在同步的時候,Hibernate會自動增加版本號。

當然,如果你的應用是在一個低數據并發環境下,并不需要版本檢查的話,你照樣可以使用 這種方式,只不過跳過版本檢查就是了。在這種情況下,最晚提交生效 (last commit wins)就是你的長對話的默認處理策略。 請記住這種策略可能會讓應用軟件的用戶感到困惑,因為他們有可能會碰上更新丟失掉卻沒 有出錯信息,或者需要合并更改沖突的情況。

很明顯,手工進行版本檢查只適合于某些軟件規模非常小的應用場景,對于大多數軟件應用場景 來說并不現實。通常情況下,不僅是單個對象實例需要進行版本檢查,整個被修改過的關 聯對象圖也都需要進行版本檢查。作為標準設計范例,Hibernate使用擴展周期的 Session的方式,或者脫管對象實例的方式來提供自動版本檢查。

2. 擴展周期的session和自動版本化

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

在等待用戶交互的時候, Session 斷開底層的JDBC連接。這種方式 以數據庫訪問的角度來說是***效的方式。應用程序不需要關心版本檢查或脫管對象實例 的重新關聯,在每個數據庫事務中,應用程序也不需要載入讀取對象實例。

  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中開啟一個新的數據庫事務,會導致session獲取一個新的連接,并恢復session的功能。將數據庫事務提交,使得session從JDBC連接斷開,并將此連接交還給連接池。在重新連接之后,要強制對你沒有更新的數據進行一次版本檢查,你可以對所有可能被其他事務修改過的對象,使用參數LockMode.READ來調用Session.lock()。你不用lock任何你正在更新的數據。

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

如果在用戶思考的過程中,Session因為太大了而不能保存,那么這種模式是有 問題的。舉例來說,一個HttpSession應該盡可能的小。由于 Session是一級緩存,并且保持了所有被載入過的對象,因此 我們只應該在那些少量的request/response情況下使用這種策略。你應該只把一個Session用于單個對話,因為它很快就會出現臟數據。

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

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

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

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

這種方式下,與持久化存儲的每次交互都發生在一個新的Session中。 然而,同一持久化對象實例可以在多次與數據庫的交互中重用。應用程序操縱脫管對象實例 的狀態,這個脫管對象實例最初是在另一個Session 中載入的,然后 調用 Session.update(),Session.saveOrUpdate(), 或者 Session.merge() 來重新關聯該對象實例。

  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會再一次在同步的時候檢查對象實例的版本,如果發生更新沖突,就拋出異常。

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

4. 定制自動版本化行為

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

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

有些情況下,只要更改不發生交錯,并發修改也是允許的。當你在 的映射中設置optimistic-lock="dirty",Hibernate在同步的時候將只比較有臟 數據的字段。

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

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

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

【編輯推薦】

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

2025-06-12 08:01:03

2010-08-18 09:00:38

數據庫

2009-09-23 10:14:10

Hibernate使用

2021-01-15 05:12:14

Java并發樂觀鎖

2009-09-25 16:43:44

Hibernate悲觀Hibernate樂觀

2017-08-21 10:56:55

MySQL并發控制

2023-10-13 00:00:00

并發樂觀鎖CAS

2022-12-12 09:07:06

Redis并發限流

2024-06-17 08:40:16

2012-02-02 15:57:09

HibernateJava

2023-07-05 08:18:54

Atomic類樂觀鎖悲觀鎖

2020-07-06 08:03:32

Java悲觀鎖樂觀鎖

2010-11-08 10:57:05

SQL Server的

2024-04-30 10:29:46

前端開發h5開發函數

2021-06-29 23:40:19

Golang語言并發

2021-04-07 06:00:18

JavaScript 前端并發控制

2021-01-12 10:22:45

JavaScript并發控制前端

2023-11-09 15:28:32

Spring開發

2024-09-03 15:14:42

2017-02-28 17:46:15

Linux驅動技術并發控制
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久国产精品视频 | 国产精品久久精品 | 久久久久久国产免费视网址 | 国产在线一区二区三区 | 亚洲国产欧美一区二区三区久久 | 欧美一级小视频 | 久久99国产精品久久99果冻传媒 | 久久久久久久久一区 | 天天射天天操天天干 | 亚洲男女激情 | 中文字幕一区二区三区在线观看 | 久草在线在线精品观看 | 久久视频免费看 | 日韩欧美在线视频 | 免费v片| 国产精品久久久久久久久久三级 | 免费看欧美一级片 | 国产精品久久久爽爽爽麻豆色哟哟 | 日一区二区 | 欧美一区二区免费视频 | 日韩成人在线播放 | 中文字幕一区二区三区四区五区 | 精品一二三| h视频在线免费 | 精品一区二区三区在线视频 | 一级毛片在线视频 | 99精品免费在线观看 | 日本黄色一级片视频 | 日本在线观看视频 | 欧美精品第一页 | 色综合一区 | 国产精品99视频 | 午夜视频一区二区三区 | 久久久久久国产精品 | 在线国产视频 | 成人免费在线视频 | 久草视频在线播放 | 色综合久久久 | 日韩中文字幕一区 | 免费午夜视频在线观看 | 国产福利在线看 |