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

          我的Java Blog

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

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

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

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

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

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

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

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

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

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

                   

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

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

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

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

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

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

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

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

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

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


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

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


          網(wǎng)站導航:
           
          主站蜘蛛池模板: 特克斯县| 日喀则市| 玉林市| 乌兰县| 太原市| 武宣县| 苏州市| 平山县| 沁阳市| 富民县| 白河县| 交口县| 同江市| 沅江市| 察雅县| 多伦县| 龙川县| 嘉兴市| 武陟县| 潮安县| 固始县| 梁山县| 乡宁县| 淮阳县| 连江县| 海安县| 平塘县| 双牌县| 阿拉善左旗| 上栗县| 北京市| 东乡族自治县| 普格县| 鄂州市| 阿拉善右旗| 革吉县| 西安市| 玉门市| 赤峰市| 漳浦县| 新建县|