<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 事 務(wù)控 制

    每個(gè)業(yè)務(wù)邏輯方法都是由一系列的數(shù)據(jù)庫(kù)訪問完成,這一系列的數(shù)據(jù)訪問可能會(huì)修改多條數(shù)據(jù)記錄,這系列的修改應(yīng)該是一個(gè)整體,絕不能僅修改其中的幾條。也就是說(shuō),多個(gè)數(shù)據(jù)庫(kù)原子訪問應(yīng)該綁定成一個(gè)整體——這就是事務(wù)。事務(wù)是一個(gè)最小的邏輯執(zhí)行單元,整個(gè)事務(wù)不能分開執(zhí)行,要么同時(shí)執(zhí)行,要么同時(shí)放棄執(zhí)行。

    4.7.1 事務(wù)的概念

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

    通常來(lái)講,事務(wù)具備如下4個(gè)特性:原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持續(xù)性(durability)。這4個(gè)特性也簡(jiǎn)稱為ACID性。

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

    ?? ● 一致性:事務(wù)執(zhí)行的結(jié)果,必須使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài),變到另一個(gè)一致性狀態(tài)。當(dāng)數(shù)據(jù)庫(kù)只包含事務(wù)成功提交的結(jié)果時(shí),數(shù)據(jù)庫(kù)處于一致性狀態(tài)。如果系統(tǒng)運(yùn)行發(fā)生中斷,某個(gè)事務(wù)尚未完成而被迫中斷,而該未完成的事務(wù)對(duì)數(shù)據(jù)庫(kù)所做的修改已被寫入數(shù)據(jù)庫(kù),此時(shí),數(shù)據(jù)庫(kù)就處于一種不正確的狀態(tài)。比如銀行在兩個(gè)賬戶之間轉(zhuǎn)賬,從A賬戶向B賬戶轉(zhuǎn)入1000元。系統(tǒng)先減少A賬戶的1000元,然后再為B賬戶增加1000元。如果全部執(zhí)行成功,數(shù)據(jù)庫(kù)處于一致性狀態(tài)。如果僅執(zhí)行完A賬戶金額的修改,而沒有增加B賬戶的金額,則數(shù)據(jù)庫(kù)就處于不一致性狀態(tài)。因此,一致性是通過(guò)原子性來(lái)保證的。

    ?? ● 隔離性:各個(gè)事務(wù)的執(zhí)行互不干擾,任意一個(gè)事務(wù)的內(nèi)部操作對(duì)其他并發(fā)的事務(wù),都具有隔離性。也即并發(fā)執(zhí)行的事務(wù)之間不能互相影響。

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

    4.7.2 Hibernate的事務(wù)

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

    Hibernate中SessionFactory對(duì)象的創(chuàng)建代價(jià)很高,它是線程安全的對(duì)象,被設(shè)計(jì)成可以為所有的應(yīng)用程序線程所共享。通常,SessionFactory會(huì)在應(yīng)用程序啟動(dòng)時(shí)創(chuàng)建,一旦創(chuàng)建了SessionFactory將不會(huì)輕易關(guān)閉,只有當(dāng)應(yīng)用關(guān)閉時(shí),SessionFactory才會(huì)關(guān)閉。

    而Session的對(duì)象是輕量級(jí)的,它也是線程不安全的。對(duì)于單個(gè)業(yè)務(wù)進(jìn)程單個(gè)工作單元而言,Session只被使用一次。創(chuàng)建Session時(shí),并不會(huì)立即打開與數(shù)據(jù)庫(kù)之間的連接,Session只在需要進(jìn)行數(shù)據(jù)庫(kù)操作時(shí),才會(huì)獲取JDBC連接。因此,打開和關(guān)閉Session,并不會(huì)對(duì)性能造成很大的影響。甚至即使無(wú)法確定一個(gè)請(qǐng)求是否需要數(shù)據(jù)訪問,也可以打開Session對(duì)象,因?yàn)槿绻贿M(jìn)行數(shù)據(jù)庫(kù)訪問,Session不會(huì)獲取JDBC連接。

    相反,數(shù)據(jù)庫(kù)事務(wù)應(yīng)該盡可能的短。從而,降低數(shù)據(jù)庫(kù)鎖定造成的資源爭(zhēng)用。數(shù)據(jù)庫(kù)長(zhǎng)事務(wù)會(huì)導(dǎo)致應(yīng)用程序無(wú)法承載高并發(fā)的負(fù)荷。

    由上面的介紹可知,Hiberante的Session和事務(wù)是緊密相關(guān)的,因?yàn)槭聞?wù)是通過(guò)Session來(lái)打開的。那么事務(wù)的范圍是多大?單個(gè)Session可以跨越多個(gè)數(shù)據(jù)庫(kù)事務(wù)嗎?事務(wù)和Session的對(duì)應(yīng)關(guān)系又如何呢?下面將介紹Hibernate Session和事務(wù)的關(guān)系。

    4.7.3 事務(wù)和Session

    數(shù)據(jù)庫(kù)操作必須在Hibernate的Session管理下進(jìn)行,但不推薦因?yàn)橐淮魏?jiǎn)單的數(shù)據(jù)庫(kù)原子調(diào)用,就打開和關(guān)閉一次Session,數(shù)據(jù)庫(kù)事務(wù)也是如此。因?yàn)椋瑢?duì)于一次原子操作打開的事務(wù)沒有任何意義——事務(wù)應(yīng)該是將多個(gè)操作步驟組合成一個(gè)邏輯整體。

    事務(wù)是按順序發(fā)送并組成一個(gè)邏輯整體的原子操作單元。

    注意:也就是說(shuō)單個(gè)的SQL語(yǔ)句發(fā)送之后,自動(dòng)事務(wù)提交模式失效了。這種自動(dòng)提交模式僅為SQL控制臺(tái)設(shè)計(jì),在實(shí)際項(xiàng)目沒有太大的實(shí)用價(jià)值。Hibernate禁止事務(wù)立即自動(dòng)提交模式,或者讓應(yīng)用服務(wù)器禁止事務(wù)自動(dòng)提交。

    通常,建議每個(gè)請(qǐng)求對(duì)應(yīng)一個(gè)Session。在這種模式下,來(lái)自客戶端的請(qǐng)求被發(fā)送到服務(wù)器端,此處可能對(duì)應(yīng)一個(gè)業(yè)務(wù)邏輯方法。在這個(gè)業(yè)務(wù)邏輯方法內(nèi),一個(gè)新的Hibernate Session被打開,然后開始事務(wù),在事務(wù)內(nèi)執(zhí)行這個(gè)操作單元中所有的數(shù)據(jù)庫(kù)操作。一旦操作完成,需要發(fā)送給客戶端的響應(yīng)也準(zhǔn)備就緒。此時(shí),提交事務(wù),然后關(guān)閉Session。在這種模式下,Session和用戶請(qǐng)求是一對(duì)一的關(guān)系,這是一種理想的Session管理模式。

    為了達(dá)到這種效果,推薦使用一個(gè)ThreadLocal變量,把Session綁定到處理客戶端請(qǐng)求的線程上去。這種方式可以讓運(yùn)行在該線程上的所有程序代碼輕松地訪問Session。也可以在一個(gè)ThreadLocal變量中保持事務(wù)上下文環(huán)境,不過(guò)這依賴于所選擇的數(shù)據(jù)庫(kù)事務(wù)劃分機(jī)制。這種實(shí)現(xiàn)模式被稱之為ThreadLocal Session和Open Session in View。

    下面是一個(gè)HibernateUtil類,該類將Hibernate Session存放在一個(gè)ThreadLocal變量中,對(duì)于同一個(gè)線程的請(qǐng)求,將可以輕松訪問該Session。

    public class HibernateUtil

    {

    ??? public static final SessionFactory sessionFactory;

    ??? //靜態(tài)初始化塊,使用該類時(shí)使用該代碼塊

    ??? static

    ??? {

    ??????? try

    ??????? {

    ??????????? //采用默認(rèn)的hibernate.cfg.xml來(lái)啟動(dòng)一個(gè)Configuration的實(shí)例

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

    ??????????? //由Configuration的實(shí)例來(lái)創(chuàng)建一個(gè)SessionFactory實(shí)例

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

    ??????? }

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

    ??????? {

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

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

    ??????? }

    ??? }

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

    ??? 對(duì)線程同步

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

    ??? //該方法用于獲取當(dāng)前線程的Session對(duì)象

    ??? public static Session currentSession() throws HibernateException

    ??? {

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

    ??????? //如果該線程還沒有Session,則創(chuàng)建一個(gè)新的Session

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

    ??????? {

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

    ??????????? //將獲得的Session變量存儲(chǔ)在ThreadLocal變量的Session里

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

    ??????? }

    ??????? return s;

    ??? }

    ??? //該方法用于關(guān)閉當(dāng)前線程里的Session

    ??? public static void closeSession() throws HibernateException

    ??? {

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

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

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

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

    ??? }

    }

    在上面的代碼中,Hibernate Session被綁定到當(dāng)前線程。當(dāng)調(diào)用currentSession方法時(shí),如果當(dāng)前線程中的Session已經(jīng)創(chuàng)建出來(lái),那么將返回這個(gè)已經(jīng)存在的Session實(shí)例。

    每次請(qǐng)求對(duì)應(yīng)一個(gè)Session的模式不僅可以用于設(shè)計(jì)操作單元,甚至很多業(yè)務(wù)處理流程都需要組合一系列的用戶操作,即用戶對(duì)數(shù)據(jù)庫(kù)的交叉訪問。

    但是,對(duì)于企業(yè)應(yīng)用,跨用戶交互的數(shù)據(jù)庫(kù)事務(wù)是無(wú)法接受的。例如,在第一個(gè)頁(yè)面,用戶打開對(duì)話框,打開一個(gè)特定Session裝入的數(shù)據(jù),可以隨意修改對(duì)話框中的數(shù)據(jù),修改完成后,將修改結(jié)果存入數(shù)據(jù)庫(kù)。

    從用戶的角度來(lái)看,這個(gè)操作單元被稱為應(yīng)用程序長(zhǎng)事務(wù)。在一個(gè)J2EE應(yīng)用實(shí)現(xiàn)中,可以有很多方法來(lái)實(shí)現(xiàn)這種應(yīng)用程序長(zhǎng)事務(wù)。

    一個(gè)比較差的做法是,當(dāng)用戶思考時(shí),應(yīng)用程序保持Session和數(shù)據(jù)庫(kù)事務(wù)是打開的,并保持?jǐn)?shù)據(jù)庫(kù)鎖定,以阻止并發(fā)修改,從而保證數(shù)據(jù)庫(kù)事務(wù)隔離級(jí)別和原子操作。這種數(shù)據(jù)庫(kù)鎖定會(huì)導(dǎo)致應(yīng)用程序無(wú)法擴(kuò)展并發(fā)用戶的數(shù)目。

    因此,不要使用每個(gè)應(yīng)用對(duì)應(yīng)一次Hibernate Session的模式,也不要使用每次Http Session對(duì)應(yīng)一次Hibernate Session的模式。

    注意:幾乎所有情況下,都不要使用每個(gè)應(yīng)用對(duì)應(yīng)一次Hibernate Session的模式,也不要使用每次Http Session對(duì)應(yīng)一次Hibernate Session的模式。

    對(duì)于這種情況,Hibernate主要有如下兩種模式來(lái)解決這個(gè)問題:

    ?? ● 脫管對(duì)象,如果采用每次用戶請(qǐng)求對(duì)應(yīng)一次Session的模式。那么,前面載入的實(shí)例在用戶思考的過(guò)程中,始終與Session脫離,處于脫管狀態(tài)。都處于與Session脫離的狀態(tài)。Hibernate允許把脫管對(duì)象重新關(guān)聯(lián)到Session上,并且對(duì)修改進(jìn)行持久化。在這種模式下,自動(dòng)版本化被用來(lái)隔離并發(fā)修改。這種模式也被稱為使用脫管對(duì)象的每個(gè)請(qǐng)求對(duì)應(yīng)一個(gè)Hibernate Session。

    ?? ● 長(zhǎng)生命周期Session,Session可以在數(shù)據(jù)庫(kù)事務(wù)提交之后,斷開和底層的JDBC連接。當(dāng)新的客戶端請(qǐng)求到來(lái)時(shí),它又重新連接上底層的JDBC連接。這種模式被稱為每個(gè)應(yīng)用程序事務(wù)對(duì)應(yīng)一個(gè)Session,因?yàn)閼?yīng)用程序事務(wù)相當(dāng)長(zhǎng)(跨越多個(gè)用戶請(qǐng)求),所以也被稱為每次應(yīng)用事務(wù)對(duì)應(yīng)一個(gè)Hibernate Session。

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

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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲XX00视频| 337p欧洲亚洲大胆艺术| 美女被免费网站91色| 亚洲视频在线观看免费| 免费观看美女裸体网站| 国产精品美女久久久免费| 亚洲精品福利网站| 国产中文字幕免费观看| 久久免费观看国产99精品| 亚洲国产乱码最新视频| 亚洲色欲一区二区三区在线观看| 最近中文字幕电影大全免费版| 亚洲av无码一区二区三区四区 | 无码精品A∨在线观看免费| 久久亚洲AV成人无码国产电影| 亚洲国产精品成人久久| 成年在线网站免费观看无广告| 免费毛片在线看不用播放器| 亚洲风情亚Aⅴ在线发布| 国产l精品国产亚洲区在线观看| 在线观看免费大黄网站| 无码国产精品一区二区免费16| 美女黄频a美女大全免费皮| 久久精品国产亚洲av影院| 波多野结衣免费视频观看| 插B内射18免费视频| 成人免费av一区二区三区| 亚洲人成网站在线播放2019 | 亚洲成a人片在线不卡一二三区| 国产亚洲一区二区在线观看| 国产成人无码免费视频97| 国产成人免费高清激情明星| 免费看一区二区三区四区| 免费国产在线精品一区| 亚洲深深色噜噜狠狠网站| 亚洲成人在线电影| 国产日韩成人亚洲丁香婷婷| 国产精品公开免费视频| 97在线线免费观看视频在线观看 | 亚洲精品久久久www| 女人张开腿给人桶免费视频|