Kava Pava Gava Tava Nava Zava Java

          everything about Java
          隨筆 - 15, 文章 - 0, 評論 - 1, 引用 - 0
          數(shù)據(jù)加載中……

          總結(jié) Hibernate 的 Optimistic Concurrency Control

          閱讀 Hibernate Reference 第11章11.3后我的總結(jié)以及理解:

          (1)帶有版本標記的 Optimistic Concurency Control 是唯一既能提供高度并發(fā),又能提供可擴展性的解決方案。就是說,很多人可以一起對一些數(shù)據(jù)同時進行操作,而這些操作又盡量不會造成互相沖突。

          (2)在并發(fā)要求低的環(huán)境里(沒有很多用戶,沒有很多更新,大家不會同時對一個數(shù)據(jù)操作,或者即使造成沖突后果也不嚴重),如果干脆不進行版本檢查,會得到“last commit wins”的結(jié)果,就是說最后 commit 的數(shù)據(jù)覆蓋之前 commit 的數(shù)據(jù)。如果兩個對話重疊,之前commit 的數(shù)據(jù)可能被后 commit 的數(shù)據(jù)覆蓋,從而丟失。而且整個過程沒有任何出錯,會造成用戶迷惑。

          (3)Extended session and automatic versioning

          用戶的會話 (conversation) 通常包括多個步驟,即取出數(shù)據(jù),操作數(shù)據(jù),然后保存數(shù)據(jù)回數(shù)據(jù)庫。這樣的會話會跨越幾個 http 來回,持續(xù)一段時間。Extended session and automatic versioning 在整個會話中只使用一個 hibernate session。在會話初始獲得 session,僅在會話結(jié)束時進行 session.flush(); ... session.close()。

          一個 hibernate session 并不對應一個 JDBC connection。開始一個transaction的時候獲得一個新的連接,并且 resume session;commit transaction 的時候切斷 hibernate session 和 JDBC connection 的連接,也就是將 connection 還給連接池。在一個 hibernate session 中,也就是,在這種方式(Extended session)中,仍然動態(tài)地使用 JDBC connection,不會造成占用太多 connection。早先版本的 hibernate 需要寫代碼 disconnect / recommect 一個 hibernate session。現(xiàn)在已經(jīng)不需這樣做(deprecated)。開始/結(jié)束 transaction 產(chǎn)生同樣效果。

          如果在session和JDBC connection重新連接的時候,如果希望強制檢查應用程序沒有進行更新,但是有可能被其他 transaction 更新的對象的版本,可以用該對象以及LockMode.READ作為參數(shù)調(diào)用 Session.lock()。Session.lock()的文檔如下:“Obtain the specified lock level upon the given object. This may be used to perform a version check (LockMode.READ), to upgrade to a pessimistic lock (LockMode.UPGRADE), or to simply reassociate a transient instance with a session (LockMode.NONE). This operation cascades to associated instances if the association is mapped with cascade="lock". ”Session.lock()的聲明如下:

          public void lock(Object object,
                           LockMode lockMode)
                    
          throws HibernateException

          采用 extended session 這種方式,所使用的 Session 通常被設(shè)置為 FlushMode.MANUAL,這樣僅僅在最后一個 transaction 周期(上面說到,一個Session可以有多個transaction)才允許進行向數(shù)據(jù)庫保存數(shù)據(jù)的操作。這個最后的 transaction 包含了 flush() 和 close() 操作,來結(jié)束對話。

          采用 extended session 的問題是,session 可能保存了很多數(shù)據(jù),占據(jù)很大空間,而用戶考慮的時間可能很長,就是說會話持續(xù)的時間很長,這樣保存 session 在一個長時間的會話中可能會造成困難。比如說,HttpSession中應該只保存很少的數(shù)據(jù)。(HttpSession可能要在各個服務器之間傳遞)因為 Session 實際上是所有取出來的對象的第一級緩存,因此最好僅僅將 extended session 用在有限的幾個 request / response 組成的會話中。一個 Session 只用在一個會話中,因為(否則?)Session中很快就會出現(xiàn)不同步(陳舊)的數(shù)據(jù)。

          Disconnected session 應該被放在持久層。可以把它放在 EJB stateful session bean 中。不要把 Session 交給 web 層,或者放在 HttpSession 中。

          使用 session-per-conversion (也就是 extended session),更難實現(xiàn)自動 current session context 管理(沒法用 ThreadLocalSessionContext了)。需要自己實現(xiàn) CurrentSessionContext。更多的需要閱讀 Hibernate Wiki。

          (4)Detached objects and automatic versioning

          這種方法,在每次和數(shù)據(jù)庫打交道的時候打開一個新的 Session。但是每次和數(shù)據(jù)庫打交道的時候重復使用同樣的持久對象實例。應用程序從一個Session中調(diào)出持久對象,對它們(此時已經(jīng) detached)進行操作,然后調(diào)用另一個 Session 的 update(), saveOrUpdate() 或者 merge(),將它們 reattach 回這個 Session。

          注意 update(), saveOrUpdate(), merge() 的區(qū)別。引用 Hibernate Reference 10.7 “Usually update() or saveOrUpdate() are used in the following scenario: ...... and merge() is very different”

          Hibernate 在 flush 的時候檢查版本,如果有沖突,拋出異常。

          如果確信(筆者認為應該說希望確信)對象沒有被更改,可以如同上面所說的調(diào)用 lock(),而不是update()。

          (5)定制自動版本檢查

          映射屬性 optimistic-lock 定制自動版本檢查。

          false: 關(guān)閉檢查

          all: 檢查所有的欄位,而不是版本欄位。這種方法可以對沒有版本欄位也無法添加版本欄位的數(shù)據(jù)庫表進行檢查。理論上來說,這種方法只能用于 extended session 而不是 session per request with detached objects,也就是上面說的方法(3)而不是(4)。原因是,這種方法需要在 Session 中保存有老的數(shù)據(jù),以便比較老的數(shù)據(jù)和數(shù)據(jù)庫中的當前數(shù)據(jù),來確定是否有沖突。

          dirty: 僅僅在 flush 時比較更改過的(dirty)數(shù)據(jù)在數(shù)據(jù)庫中有沒有被其他 transaction 修改過,以便避免沖突。這種方法可以允許同時修改一行數(shù)據(jù)中的不重疊的字段。我的理解,dirty 同 all 一樣,都只能在 extended session 中使用,以便利用 extended session 中保存的老的數(shù)據(jù)進行比較(版本檢查)。

          所有以上情況,不管是使用版本欄目,還是 all 或 dirty,Hibernate 都在一個 UPDATE 語句中完成檢查和更新(在 Where 從句中設(shè)置檢查條件)。

          最后,如果設(shè)置了 transitive persistence 到關(guān)聯(lián)管理的從屬 entity,hibernate 可能會執(zhí)行不必要的 update。這通常不是問題。但是,如果有數(shù)據(jù)庫 trigger 關(guān)聯(lián)到 update 時,可能實際上沒有更新但是會引發(fā) trigger。可以設(shè)置 select-before-update="true" 強制 hibernate 在更新前進行 select。

          posted on 2009-12-16 12:27 bing 閱讀(1604) 評論(0)  編輯  收藏 所屬分類: Hibernate

          主站蜘蛛池模板: 包头市| 大洼县| 苏尼特右旗| 永善县| 涿鹿县| 柳江县| 东乌珠穆沁旗| 新和县| 广德县| 疏勒县| 清苑县| 桐乡市| 新田县| 蕲春县| 天长市| 丹东市| 霍州市| 昌黎县| 宁强县| 宜城市| 霍林郭勒市| 高淳县| 平塘县| 当涂县| 莫力| 老河口市| 鄂伦春自治旗| 湾仔区| 固始县| 马关县| 翁牛特旗| 南召县| 乌拉特前旗| 陕西省| 宁武县| 开化县| 鄄城县| 汝南县| 夏津县| 襄城县| 无锡市|