<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,  comments - 11,  trackbacks - 0

    4.7 事 務控 制

    每個業務邏輯方法都是由一系列的數據庫訪問完成,這一系列的數據訪問可能會修改多條數據記錄,這系列的修改應該是一個整體,絕不能僅修改其中的幾條。也就是說,多個數據庫原子訪問應該綁定成一個整體——這就是事務。事務是一個最小的邏輯執行單元,整個事務不能分開執行,要么同時執行,要么同時放棄執行。

    4.7.1 事務的概念

    事務是一步或幾步基本操作組成的邏輯執行單元,這些基本操作作為一個整體執行單元,它們要么全部執行,要么全部取消,絕不能僅僅執行部分。一般而言,每次用戶請求,對應一個業務邏輯方法,一個業務邏輯方法往往具有邏輯上的原子性,應該使用事務。例如,一個轉賬操作,對應修改兩個賬戶的余額,這兩個賬戶的修改要么同時生效,要么同時取消——同時生效是轉賬成功,同時取消是轉賬失敗;但不可只修改其中一個賬戶,那將破壞數據庫的完整性。

    通常來講,事務具備如下4個特性:原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持續性(durability)。這4個特性也簡稱為ACID性。

    ?? ● 原子性:事務是應用中最小執行單位,就如原子是自然界最小顆粒,具有不可再分的特征一樣。事務是應用中不可再分的最小邏輯執行體。

    ?? ● 一致性:事務執行的結果,必須使數據庫從一個一致性狀態,變到另一個一致性狀態。當數據庫只包含事務成功提交的結果時,數據庫處于一致性狀態。如果系統運行發生中斷,某個事務尚未完成而被迫中斷,而該未完成的事務對數據庫所做的修改已被寫入數據庫,此時,數據庫就處于一種不正確的狀態。比如銀行在兩個賬戶之間轉賬,從A賬戶向B賬戶轉入1000元。系統先減少A賬戶的1000元,然后再為B賬戶增加1000元。如果全部執行成功,數據庫處于一致性狀態。如果僅執行完A賬戶金額的修改,而沒有增加B賬戶的金額,則數據庫就處于不一致性狀態。因此,一致性是通過原子性來保證的。

    ?? ● 隔離性:各個事務的執行互不干擾,任意一個事務的內部操作對其他并發的事務,都具有隔離性。也即并發執行的事務之間不能互相影響。

    ?? ● 持續性:持續性也稱為持久性(persistence),指事務一旦提交,對數據所做的任何改變,都要記錄到永久存儲器中,通常保存進物理數據庫。

    4.7.2 Hibernate的事務

    Hibernate直接使用JDBC連接和JTA資源,不添加任何附加鎖定行為。Hibernate只添加自動版本管理,而不會鎖定內存中的對象,也不會改變數據庫事務的隔離級別。基本上,使用 Hibernate就好像直接使用JDBC(或者JTA/CMT)進行數據庫訪問。

    Hibernate中SessionFactory對象的創建代價很高,它是線程安全的對象,被設計成可以為所有的應用程序線程所共享。通常,SessionFactory會在應用程序啟動時創建,一旦創建了SessionFactory將不會輕易關閉,只有當應用關閉時,SessionFactory才會關閉。

    而Session的對象是輕量級的,它也是線程不安全的。對于單個業務進程單個工作單元而言,Session只被使用一次。創建Session時,并不會立即打開與數據庫之間的連接,Session只在需要進行數據庫操作時,才會獲取JDBC連接。因此,打開和關閉Session,并不會對性能造成很大的影響。甚至即使無法確定一個請求是否需要數據訪問,也可以打開Session對象,因為如果不進行數據庫訪問,Session不會獲取JDBC連接。

    相反,數據庫事務應該盡可能的短。從而,降低數據庫鎖定造成的資源爭用。數據庫長事務會導致應用程序無法承載高并發的負荷。

    由上面的介紹可知,Hiberante的Session和事務是緊密相關的,因為事務是通過Session來打開的。那么事務的范圍是多大?單個Session可以跨越多個數據庫事務嗎?事務和Session的對應關系又如何呢?下面將介紹Hibernate Session和事務的關系。

    4.7.3 事務和Session

    數據庫操作必須在Hibernate的Session管理下進行,但不推薦因為一次簡單的數據庫原子調用,就打開和關閉一次Session,數據庫事務也是如此。因為,對于一次原子操作打開的事務沒有任何意義——事務應該是將多個操作步驟組合成一個邏輯整體。

    事務是按順序發送并組成一個邏輯整體的原子操作單元。

    注意:也就是說單個的SQL語句發送之后,自動事務提交模式失效了。這種自動提交模式僅為SQL控制臺設計,在實際項目沒有太大的實用價值。Hibernate禁止事務立即自動提交模式,或者讓應用服務器禁止事務自動提交。

    通常,建議每個請求對應一個Session。在這種模式下,來自客戶端的請求被發送到服務器端,此處可能對應一個業務邏輯方法。在這個業務邏輯方法內,一個新的Hibernate Session被打開,然后開始事務,在事務內執行這個操作單元中所有的數據庫操作。一旦操作完成,需要發送給客戶端的響應也準備就緒。此時,提交事務,然后關閉Session。在這種模式下,Session和用戶請求是一對一的關系,這是一種理想的Session管理模式。

    為了達到這種效果,推薦使用一個ThreadLocal變量,把Session綁定到處理客戶端請求的線程上去。這種方式可以讓運行在該線程上的所有程序代碼輕松地訪問Session。也可以在一個ThreadLocal變量中保持事務上下文環境,不過這依賴于所選擇的數據庫事務劃分機制。這種實現模式被稱之為ThreadLocal Session和Open Session in View。

    下面是一個HibernateUtil類,該類將Hibernate Session存放在一個ThreadLocal變量中,對于同一個線程的請求,將可以輕松訪問該Session。

    public class HibernateUtil

    {

    ??? public static final SessionFactory sessionFactory;

    ??? //靜態初始化塊,使用該類時使用該代碼塊

    ??? static

    ??? {

    ??????? try

    ??????? {

    ??????????? //采用默認的hibernate.cfg.xml來啟動一個Configuration的實例

    ??????????? Configuration configuration=new Configuration().configure();

    ??????????? //由Configuration的實例來創建一個SessionFactory實例

    ??????????? sessionFactory = configuration.buildSessionFactory();

    ??????? }

    ??????? catch (Throwable ex)

    ??????? {

    ??????????? System.err.println("初始化sessionFactory失敗." + ex);

    ??????????? throw new ExceptionInInitializerError(ex);

    ??????? }

    ??? }

    ??? //ThreadLocal是隔離多個線程的數據共享,不存在多個線程之間共享資源,因此不再需要

    ??? 對線程同步

    ??? public static final ThreadLocal session = new ThreadLocal();

    ??? //該方法用于獲取當前線程的Session對象

    ??? public static Session currentSession() throws HibernateException

    ??? {

    ??????? Session s = (Session) session.get();

    ??????? //如果該線程還沒有Session,則創建一個新的Session

    ??????? if (s == null)

    ??????? {

    ??????????? s = sessionFactory.openSession();

    ??????????? //將獲得的Session變量存儲在ThreadLocal變量的Session里

    ??????????? session.set(s);

    ??????? }

    ??????? return s;

    ??? }

    ??? //該方法用于關閉當前線程里的Session

    ??? public static void closeSession() throws HibernateException

    ??? {

    ??????? Session s = (Session) session.get();

    ??????? if (s != null)

    ??????????? s.close();

    ??????? session.set(null);

    ??? }

    }

    在上面的代碼中,Hibernate Session被綁定到當前線程。當調用currentSession方法時,如果當前線程中的Session已經創建出來,那么將返回這個已經存在的Session實例。

    每次請求對應一個Session的模式不僅可以用于設計操作單元,甚至很多業務處理流程都需要組合一系列的用戶操作,即用戶對數據庫的交叉訪問。

    但是,對于企業應用,跨用戶交互的數據庫事務是無法接受的。例如,在第一個頁面,用戶打開對話框,打開一個特定Session裝入的數據,可以隨意修改對話框中的數據,修改完成后,將修改結果存入數據庫。

    從用戶的角度來看,這個操作單元被稱為應用程序長事務。在一個J2EE應用實現中,可以有很多方法來實現這種應用程序長事務。

    一個比較差的做法是,當用戶思考時,應用程序保持Session和數據庫事務是打開的,并保持數據庫鎖定,以阻止并發修改,從而保證數據庫事務隔離級別和原子操作。這種數據庫鎖定會導致應用程序無法擴展并發用戶的數目。

    因此,不要使用每個應用對應一次Hibernate Session的模式,也不要使用每次Http Session對應一次Hibernate Session的模式。

    注意:幾乎所有情況下,都不要使用每個應用對應一次Hibernate Session的模式,也不要使用每次Http Session對應一次Hibernate Session的模式。

    對于這種情況,Hibernate主要有如下兩種模式來解決這個問題:

    ?? ● 脫管對象,如果采用每次用戶請求對應一次Session的模式。那么,前面載入的實例在用戶思考的過程中,始終與Session脫離,處于脫管狀態。都處于與Session脫離的狀態。Hibernate允許把脫管對象重新關聯到Session上,并且對修改進行持久化。在這種模式下,自動版本化被用來隔離并發修改。這種模式也被稱為使用脫管對象的每個請求對應一個Hibernate Session。

    ?? ● 長生命周期Session,Session可以在數據庫事務提交之后,斷開和底層的JDBC連接。當新的客戶端請求到來時,它又重新連接上底層的JDBC連接。這種模式被稱為每個應用程序事務對應一個Session,因為應用程序事務相當長(跨越多個用戶請求),所以也被稱為每次應用事務對應一個Hibernate Session。

    posted on 2009-07-19 09:11 jadmin 閱讀(85) 評論(0)  編輯  收藏

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


    網站導航:
     
    主站蜘蛛池模板: 国产又粗又长又硬免费视频| 精品熟女少妇av免费久久| 九九九精品成人免费视频| 亚洲视频网站在线观看| 免费国产午夜高清在线视频 | 永久免费无码网站在线观看| 亚洲一区二区三区不卡在线播放| 免费成人福利视频| 亚洲av无码片在线观看| 在线看片免费不卡人成视频| 亚洲精品无码久久久久APP| 日韩精品视频免费网址| 美女黄色免费网站| 久久久久亚洲精品天堂久久久久久| 一区二区三区免费在线视频 | 亚洲永久在线观看| 免费无码黄动漫在线观看| 国产亚洲视频在线| 在线播放亚洲第一字幕| 久久一本岛在免费线观看2020| 久久精品蜜芽亚洲国产AV| 中文字幕无码成人免费视频 | 国产性生大片免费观看性| 亚洲成AV人片在WWW色猫咪| 18女人水真多免费高清毛片| 四虎必出精品亚洲高清| 一本色道久久88综合亚洲精品高清| g0g0人体全免费高清大胆视频| 亚洲AV无码成人网站久久精品大 | 免费看小12萝裸体视频国产| 国产精品免费一区二区三区| 亚洲尹人九九大色香蕉网站| 在线观看免费人成视频色| 免费大片av手机看片| 日韩亚洲欧洲在线com91tv| 免费国产作爱视频网站| 成人福利在线观看免费视频| 久久久久亚洲精品无码蜜桃| 国产中文字幕免费| 4444www免费看| 欧亚一级毛片免费看|