Hibernate事務併發之深入理解

 

基於歷史遺留原因和存儲、查詢的效率考慮,我覺得原先的關係型數據庫短期內不大可能變成完全面向對象的,
 
而我們業務系統大多又在對象的基礎上建模,對於這些系統,O/R映射是必須的,hibernate是O/R框架中的佼佼
 
者,hibernate能夠成爲jboss中持久層的實現就是一個不爭的事實,對於利用struts-spring-hibernate
 
輕型框架構建的系統來說,hibernate無疑也是其中的攻堅部分。的確,在我接觸struts、spring 甚至 ejb3.0中的部
分東西以後,始終覺得hibernate或者持久層的實現是關乎一個系統性能的最最關鍵。
 
我覺得hibernate的重點無外乎幾個方面
 
(1) 關係型數據庫記錄到對象的映射(即數據庫schema到java類的映射)
 
(2) 數據庫表關聯到java對象的映射(一對多,多對一,多對多,一對一等)
 
(3) 各種查詢的使用
 
(4) 事務(JDBC事務與JTA事務)的理解
 
(5) 緩存
 
這其中估計是表關聯映射和事務比較難理解,這裏就談點對事務的理解。
 
今天讀了hibernate參考文檔中3.2.0版本11.3.4(定製自動化版本行爲)中的一段話,話是這樣的:
 
遺留系統的數據庫Schema通常是靜態的,不可修改的。或者,其他應用程序也可能訪問同一數據 庫,
 
根本無法得知如何處理版本號,甚至時間戳。在以上的所有場景中,實現版本化不能依靠 數據庫表的
 
某個特定列。在<class>的映射中設置 optimistic-lock="all"可以在沒有版本或者時間戳屬性映射的
況下實現 版本檢查,此時Hibernate將比較一行記錄的每個字段的狀態。請注意,只有當Hibernate能
 
夠比 較新舊狀態的情況下,這種方式才能生效,也就是說, 你必須使用單個長生命週期Session模式,
 
而不能使用 session-per-request-with-detached-objects模式。
 
開始不太能理解,後來仔細琢磨,豁然開朗,可以這樣理解:
 
(1) 一般來說,hibernate在樂觀併發控制中使用版本號來檢查更改衝突,這點很容易理解,對於R記錄,可能有C1
和C2兩個人在同時修改,爲了使得C1的修改不覆蓋C2的修改(反過來也一樣),可以在R記錄結構上擴展一個
version的字段,這樣,如果C1的修改同步到數據庫時發現R記錄的版本號已經不低於C1中的版本號(表明C2已經修
改過R記錄)了,
 
就表明C1的修改必須回滾。
 
(2) 既然需要版本號來檢查事務併發中的衝突,這對於無法擴展schema的遺留系統來說當然不可行了。
 
(3) 用版本號來檢查衝突限於數據庫只被使用hibernate爲持久層的應用程序訪問。
 
(4) 由於(2)(3),可以提供optimistic-lock="all"來進行衝突檢查,如果要同步一個對象的修改到數據庫,可以
比較對象未修改之前與數據庫的記錄,如果相同,則表示對象的修改不是基於髒數據的(沒有其他人同步修改該
記錄),可以同步該修改,否則,需要回退事務。
 
(5) 上面這段話中最難理解的就是"只有當Hibernate能夠比較新舊狀態的情況下,這種方式才能生效,
 
也就是說, 你必須使用單個長生命週期Session模式,而不能使用
 
session-per-request-with-detached-objects模式"。這段話反映的一個意思就是長生命週期session模式
是可以比較新舊狀態的,而session-per-request-with-datached-object是不能比較新舊狀態的,爲什麼呢?原來
長生命週期session中的對象一直沒有脫離一個session,由於session有緩存,所以對象修改之前的狀態是存在的,
可以和數據庫記錄進行比較。而detached-objects在未發生修改前的狀態一般與session無關,沒有緩存,不得而
知,所以自然也無法與數據庫記錄比較了。
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章