因為專注,所以專業(yè)

          我的Java Blog

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            21 隨筆 :: 30 文章 :: 6 評論 :: 0 Trackbacks

          1. Session和事務(wù)范圍(transaction scope)
             SessionFactory
          對象的創(chuàng)建代價很昂貴,它是線程安全的對象,它為所有的應(yīng)用程序線程所共享。它只創(chuàng)建一次,通常是在應(yīng)用程序啟動的時候,由一個Configuraion的實例來創(chuàng)建。

          Session對象的創(chuàng)建代價比較小,是非線程安全的,對于單個請求,單個會話、單個的 工作單元而言,它只被使用一次,然后就丟棄。只有在需要的時候,一個Session對象 才會獲取一個JDBC的Connection(或一個Datasource) 對象,因此假若不使用的時候它不消費任何資源。

          此外我們還要考慮數(shù)據(jù)庫事務(wù)。數(shù)據(jù)庫事務(wù)應(yīng)該盡可能的短,降低數(shù)據(jù)庫中的鎖爭用。 數(shù)據(jù)庫長事務(wù)會阻止你的應(yīng)用程序擴展到高的并發(fā)負(fù)載。因此,假若在用戶思考期間讓數(shù)據(jù)庫事務(wù)開著,直到整個工作單元完成才關(guān)閉這個事務(wù),這絕不是一個好的設(shè)計。

          一個操作單元(Unit of work)的范圍是多大?單個的Hibernate Session能跨越多個 數(shù)據(jù)庫事務(wù)嗎?還是一個Session的作用范圍對應(yīng)一個數(shù)據(jù)庫事務(wù)的范圍?應(yīng)該何時打開 Session,何時關(guān)閉Session?,你又如何劃分?jǐn)?shù)據(jù)庫事務(wù)的邊界呢?
          1.1 操作單元(Unit of work)

                   首先,別用session-per-operation這種反模式了,也就是說,在單個線程中, 不要因為一次簡單的數(shù)據(jù)庫調(diào)用,就打開和關(guān)閉一次Session!數(shù)據(jù)庫事務(wù)也是如此。 應(yīng)用程序中的數(shù)據(jù)庫調(diào)用是按照計劃好的次序,分組為原子的操作單元。(注意,這也意味著,應(yīng)用程 序中,在單個的SQL語句發(fā)送之后,自動事務(wù)提交(auto-commit)模式失效了。這種模式專門為SQL控制臺操作設(shè)計的。 Hibernate禁止立即自動事務(wù)提交模式,或者期望應(yīng)用服務(wù)器禁止立即自動事務(wù)提交模式。)數(shù)據(jù)庫事務(wù)絕不是可有可無的,任何與數(shù)據(jù)庫之間的通訊都必須在某個事務(wù)中進(jìn)行,不管你是在讀還是在寫數(shù)據(jù)。對讀數(shù)據(jù)而言,應(yīng)該避免auto-commit行為,因為很多小的事務(wù)比一個清晰定義的工作單元性能差。后者也更容易維護(hù)和擴展。

          在多用戶的client/server應(yīng)用程序中,最常用的模式是 每個請求一個會話(session-per-request)。 在這種模式下,來自客戶端的請求被發(fā)送到服務(wù)器端(即Hibernate持久化層運行的地方),一 個新的Hibernate Session被打開,并且執(zhí)行這個操作單元中所有的數(shù)據(jù)庫操作。 一旦操作完成(同時對客戶端的響應(yīng)也準(zhǔn)備就緒),session被同步,然后關(guān)閉。你也可以使用單 個數(shù)據(jù)庫事務(wù)來處理客戶端請求,在你打開Session之后啟動事務(wù),在你關(guān)閉 Session之前提交事務(wù)。會話和請求之間的關(guān)系是一對一的關(guān)系,這種模式對 于大多數(shù)應(yīng)用程序來說是很棒的。

          實現(xiàn)才是真正的挑戰(zhàn)。Hibernate內(nèi)置了對"當(dāng)前session(current session)" 的管理,用于簡化此模式。你要做的一切就是在服務(wù)器端要處理請求的時候,開啟事務(wù),在響應(yīng)發(fā)送給客戶之前結(jié)束事務(wù)。你可以用任何方式來完成這一操作,通常的方案有ServletFilter,在service方法中進(jìn)行pointcut的AOP攔截器,或者proxy/interception容器。EJB容器是實現(xiàn)橫切諸如EJB session bean上的事務(wù)分界,用CMT對事務(wù)進(jìn)行聲明等方面的標(biāo)準(zhǔn)手段。假若你決定使用編程式的事務(wù)分界,請參考本章后面講到的Hibernate Transaction API,這對易用性和代碼可移植性都有好處。

          在任何時間,任何地方,你的應(yīng)用代碼可以通過簡單的調(diào)用sessionFactory.getCurrentSession()來訪問"當(dāng)前session",用于處理請求。你總是會得到當(dāng)前數(shù)據(jù)庫事務(wù)范圍內(nèi)的Session。在使用本地資源或JTA環(huán)境時,必須配置它,請參見第 2.5 節(jié) “上下文相關(guān)的(Contextual)Session”

          有時,將Session和數(shù)據(jù)庫事務(wù)的邊界延伸到"展示層被渲染后"會帶來便利。有些serlvet應(yīng)用程序在對請求進(jìn)行處理后,有個單獨的渲染期,這種延伸對這種程序特別有用。假若你實現(xiàn)你自己的攔截器,把事務(wù)邊界延伸到展示層渲染結(jié)束后非常容易。然而,假若你依賴有容器管理事務(wù)的EJB,這就不太容易了,因為事務(wù)會在EJB方法返回后結(jié)束,而那是在任何展示層渲染開始之前。請訪問Hibernate網(wǎng)站和論壇,你可以找到Open Session in View這一模式的提示和示例。
          1.1 長對話

                   

          session-per-request模式不僅僅是一個可以用來設(shè)計操作單元的有用概念。很多業(yè)務(wù)處理都需 要一系列完整的與用戶之間的交互,而這些用戶是指對數(shù)據(jù)庫有交叉訪問的用戶。在基于web的應(yīng)用和企業(yè) 應(yīng)用中,跨用戶交互的數(shù)據(jù)庫事務(wù)是無法接受的。考慮下面的例子:

          • 在界面的第一屏,打開對話框,用戶所看到的數(shù)據(jù)是被一個特定的 Session 和數(shù)據(jù) 庫事務(wù)載入(load)的。用戶可以隨意修改對話框中的數(shù)據(jù)對象。

          • 5分鐘后,用戶點擊“保存”,期望所做出的修改被持久化;同時他也期望自己是唯一修改這個信息的人,不會出現(xiàn) 修改沖突。

          從用戶的角度來看,我們把這個操作單元稱為長時間運行的對話(conversation),或者(or 應(yīng)用事務(wù),application transaction)。 在你的應(yīng)用程序中,可以有很多種方法來實現(xiàn)它。

          頭一個幼稚的做法是,在用戶思考的過程中,保持Session和數(shù)據(jù)庫事務(wù)是打開的, 保持?jǐn)?shù)據(jù)庫鎖定,以阻止并發(fā)修改,從而保證數(shù)據(jù)庫事務(wù)隔離級別和原子操作。這種方式當(dāng)然是一個反模式, 因為鎖爭用會導(dǎo)致應(yīng)用程序無法擴展并發(fā)用戶的數(shù)目。

          很明顯,我們必須使用多個數(shù)據(jù)庫事務(wù)來實現(xiàn)這個對話。在這個例子中,維護(hù)業(yè)務(wù)處理的 事務(wù)隔離變成了應(yīng)用程序?qū)拥牟糠重?zé)任。一個對話通常跨越多個數(shù)據(jù)庫事務(wù)。如果僅僅只有一 個數(shù)據(jù)庫事務(wù)(最后的那個事務(wù))保存更新過的數(shù)據(jù),而所有其他事務(wù)只是單純的讀取數(shù)據(jù)(例如在一 個跨越多個請求/響應(yīng)周期的向?qū)эL(fēng)格的對話框中),那么應(yīng)用程序事務(wù)將保證其原子性。這種方式比聽 起來還要容易實現(xiàn),特別是當(dāng)你使用了Hibernate的下述特性的時候:

          • 自動版本化 - Hibernate能夠自動進(jìn)行樂觀并發(fā)控制 ,如果在用戶思考 的過程中發(fā)生并發(fā)修改,Hibernate能夠自動檢測到。一般我們只在對話結(jié)束時才檢查。

          • 脫管對象(Detached Objects)- 如果你決定采用前面已經(jīng)討論過的 session-per-request模式,所有載入的實例在用戶思考的過程 中都處于與Session脫離的狀態(tài)。Hibernate允許你把與Session脫離的對象重新關(guān)聯(lián)到Session 上,并且對修改進(jìn)行持久化,這種模式被稱為 session-per-request-with-detached-objects。自動版本化被用來隔離并發(fā)修改。

          • Extended (or Long) Session - Hibernate 的Session 可以在數(shù)據(jù)庫事務(wù)提交之后和底層的JDBC連接斷開,當(dāng)一個新的客戶端請求到來的時候,它又重新連接上底層的 JDBC連接。這種模式被稱之為session-per-conversation,這種情況可 能會造成不必要的Session和JDBC連接的重新關(guān)聯(lián)。自動版本化被用來隔離并發(fā)修改, Session通常不允許自動flush,而是明確flush。

          session-per-request-with-detached-objectssession-per-conversation 各有優(yōu)缺點,我們在本章后面樂觀并發(fā) 控制那部分再進(jìn)行討論。


          posted on 2010-05-20 00:04 kevin.zhan 閱讀(208) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 交城县| 万年县| 刚察县| 淮滨县| 淮南市| 梨树县| 敦煌市| 柘荣县| 广安市| 酉阳| 仙居县| 天祝| 凤城市| 云和县| 固始县| 平阴县| 福建省| 龙口市| 萍乡市| 柳河县| 长武县| 富民县| 江山市| 饶阳县| 西安市| 鄢陵县| 二手房| 墨脱县| 仙游县| 五峰| 中方县| 天镇县| 大荔县| 武邑县| 江达县| 宁晋县| 平潭县| 上饶市| 锦屏县| 水城县| 拉萨市|