hibernate事務(wù)-創(chuàng)新互聯(lián)

hibernate事務(wù)

9.3 Hibernate的事務(wù)管理 事務(wù)(Transaction)是工作中的基本邏輯單位,可以用于確保數(shù)據(jù)庫能夠被正確修改,避免數(shù)據(jù)只修改了一部分而導致數(shù)據(jù)不完整,或者在修改時受到用戶干擾。作為一名軟件設(shè)計師,必須了解事務(wù)并合理利用,以確保數(shù)據(jù)庫保存正確、完整的數(shù)據(jù)。數(shù)據(jù)庫向用戶提供保存當前程序狀態(tài)的方法,叫事務(wù)提交(commit);當事務(wù)執(zhí)行過程中,使數(shù)據(jù)庫忽略當前的狀態(tài)并回到前面保存的狀態(tài)的方法叫事務(wù)回滾(rollback)。hibernate事務(wù)
9.3.1 事務(wù)的特性

事務(wù)具備原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)4個屬性,簡稱ACID。下面對這4個特性分別進行說明。

創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)由有經(jīng)驗的網(wǎng)站設(shè)計師、開發(fā)人員和項目經(jīng)理組成的專業(yè)建站團隊,負責網(wǎng)站視覺設(shè)計、用戶體驗優(yōu)化、交互設(shè)計和前端開發(fā)等方面的工作,以確保網(wǎng)站外觀精美、網(wǎng)站制作、做網(wǎng)站易于使用并且具有良好的響應(yīng)性。

l        原子性:將事務(wù)中所做的操作捆綁成一個原子單元,即對于事務(wù)所進行的數(shù)據(jù)修改等操作,要么全部執(zhí)行,要么全部不執(zhí)行。

l        一致性:事務(wù)在完成時,必須使所有的數(shù)據(jù)都保持一致狀態(tài),而且在相關(guān)數(shù)據(jù)中,所有規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持所有數(shù)據(jù)的完整性。事務(wù)結(jié)束時,所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)都應(yīng)該是正確的。

l        隔離性:由并發(fā)事務(wù)所做的修改必須與任何其他事務(wù)所做的修改相隔離。事務(wù)查看數(shù)據(jù)時數(shù)據(jù)所處的狀態(tài),要么是被另一并發(fā)事務(wù)修改之前的狀態(tài),要么是被另一并發(fā)事務(wù)修改之后的狀態(tài),即事務(wù)不會查看由另一個并發(fā)事務(wù)正在修改的數(shù)據(jù)。這種隔離方式也叫可串行性。

l        持久性:事務(wù)完成之后,它對系統(tǒng)的影響是永久的,即使出現(xiàn)系統(tǒng)故障也是如此。

9.3.2 事務(wù)隔離

事務(wù)隔離意味著對于某一個正在運行的事務(wù)來說,好像系統(tǒng)中只有這一個事務(wù),其他并發(fā)的事務(wù)都不存在一樣。在大部分情況下,很少使用完全隔離的事務(wù)。但不完全隔離的事務(wù)會帶來如下一些問題。

l        更新丟失(Lost Update):兩個事務(wù)都企圖去更新一行數(shù)據(jù),導致事務(wù)拋出異常退出,兩個事務(wù)的更新都白費了。

l        臟數(shù)據(jù)(Dirty Read):如果第二個應(yīng)用程序使用了第一個應(yīng)用程序修改過的數(shù)據(jù),而這個數(shù)據(jù)處于未提交狀態(tài),這時就會發(fā)生臟讀。第一個應(yīng)用程序隨后可能會請求回滾被修改的數(shù)據(jù),從而導致第二個事務(wù)使用的數(shù)據(jù)被損壞,即所謂的“變臟”。

l        不可重讀(Unrepeatable Read):一個事務(wù)兩次讀同一行數(shù)據(jù),可是這兩次讀到的數(shù)據(jù)不一樣,就叫不可重讀。如果一個事務(wù)在提交數(shù)據(jù)之前,另一個事務(wù)可以修改和刪除這些數(shù)據(jù),就會發(fā)生不可重讀。

l        幻讀(Phantom Read):一個事務(wù)執(zhí)行了兩次查詢,發(fā)現(xiàn)第二次查詢結(jié)果比第一次查詢多出了一行,這可能是因為另一個事務(wù)在這兩次查詢之間插入了新行。

針對由事務(wù)的不完全隔離所引起的上述問題,提出了一些隔離級別,用來防范這些問題。

l        讀操作未提交(Read Uncommitted):說明一個事務(wù)在提交前,其變化對于其他事務(wù)來說是可見的。這樣臟讀、不可重讀和幻讀都是允許的。當一個事務(wù)已經(jīng)寫入一行數(shù)據(jù)但未提交,其他事務(wù)都不能再寫入此行數(shù)據(jù);但是,任何事務(wù)都可以讀任何數(shù)據(jù)。這個隔離級別使用排寫鎖實現(xiàn)。

l        讀操作已提交(Read Committed):讀取未提交的數(shù)據(jù)是不允許的,它使用臨時的共讀鎖和排寫鎖實現(xiàn)。這種隔離級別不允許臟讀,但不可重讀和幻讀是允許的。

l        可重讀(Repeatable Read):說明事務(wù)保證能夠再次讀取相同的數(shù)據(jù)而不會失敗。此隔離級別不允許臟讀和不可重讀,但幻讀會出現(xiàn)。

l        可串行化(Serializable):提供最嚴格的事務(wù)隔離。這個隔離級別不允許事務(wù)并行執(zhí)行,只允許串行執(zhí)行。這樣,臟讀、不可重讀或幻讀都可發(fā)生。

事務(wù)隔離與隔離級別的關(guān)系如表9-2所示。

表9-2 事務(wù)隔離與隔離級別的關(guān)系

隔 離 級 別

臟讀(Dirty Read)

不可重讀(Unrepeatable read)

幻讀(Phantom Read)

讀操作未提交(Read Uncommitted)

可能

可能

可能

讀操作已提交(Read Committed)

不可能

可能

可能

可重讀(Repeatable Read)

不可能

不可能

可能

可串行化(Serializable)

不可能

不可能

不可能

在一個實際應(yīng)用中,開發(fā)者經(jīng)常不能確定使用什么樣的隔離級別。太嚴厲的級別將降低并發(fā)事務(wù)的性能,但是不足夠的隔離級別又會產(chǎn)生一些小的Bug,而這些Bug只會在系統(tǒng)重負荷(也就是并發(fā)嚴重時)的情況下才會出現(xiàn)。

一般來說,讀操作未提交(Read Uncommitted)是很危險的。一個事務(wù)的回滾或失敗都會影響到另一個并行的事務(wù),或者說在內(nèi)存中留下和數(shù)據(jù)庫中不一致的數(shù)據(jù)。這些數(shù)據(jù)可能會被另一個事務(wù)讀取并提交到數(shù)據(jù)庫中。這是完全不允許的。

另外,大部分程序并不需要可串行化隔離(Serializable Isolation)。雖然,它不允許幻讀,但一般來說,幻讀并不是一個大問題??纱谢綦x需要很大的系統(tǒng)開支,很少有人在實際開發(fā)中使用這種事務(wù)隔離模式。

現(xiàn)在留下來的可選的隔離級別是讀操作已提交(Read Committed)和可重讀(Repeatable Read)。Hibernate可以很好地支持可重讀(Repeatable Read)隔離級別。

9.3.3 在Hibernate配置文件中設(shè)置隔離級別

JDBC連接數(shù)據(jù)庫使用的是默認隔離級別,即讀操作已提交(Read Committed)和可重讀(Repeatable Read)。在Hibernate的配置文件hibernate.properties中,可以修改隔離級別:

#hibernate.connection.isolation 4

在上一行代碼中,Hibernate事務(wù)的隔離級別是4,這是什么意思呢?級別的數(shù)字意義如下。

l        1:讀操作未提交(Read Uncommitted)

l        2:讀操作已提交(Read Committed)

l        4:可重讀(Repeatable Read)

l        8:可串行化(Serializable)

因此,數(shù)字4表示“可重讀”隔離級別。如果要使以上語句有效,應(yīng)把此語句行前的注釋符“#”去掉:

hibernate.connection.isolation 4

也可以在配置文件hibernate.cfg.xml中加入以下代碼:

<session-factory>

…..

//把隔離級別設(shè)置為4

<property name=” hibernate.connection.isolation”>4</property>

……

</session-factory>

在開始一個事務(wù)之前,Hibernate從配置文件中獲得隔離級別的值。

9.3.4 在Hibernate中使用JDBC事務(wù)

Hibernate對JDBC進行了輕量級的封裝,它本身在設(shè)計時并不具備事務(wù)處理功能。Hibernate將底層的JDBCTransaction或JTATransaction進行了封裝,再在外面套上Transaction和Session的外殼,其實是通過委托底層的JDBC或JTA來實現(xiàn)事務(wù)的處理功能的。

要在Hibernate中使用事務(wù),可以在它的配置文件中指定使用JDBCTransaction或者JTATransaction。在hibernate.properties中,查找“transaction.factory_class”關(guān)鍵字,得到以下配置:

# hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory

# hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory

Hibernate的事務(wù)工廠類可以設(shè)置成JDBCTransactionFactory或者JTATransactionFactory。如果不進行配置,Hibernate就會認為系統(tǒng)使用的事務(wù)是JDBC事務(wù)。

在JDBC的提交模式(commit mode)中,如果數(shù)據(jù)庫連接是自動提交模式(auto commit mode),那么在每一條SQL語句執(zhí)行后事務(wù)都將被提交,提交后如果還有任務(wù),那么一個新的事務(wù)又開始了。

Hibernate在Session控制下,在取得數(shù)據(jù)庫連接后,就立刻取消自動提交模式,即Hibernate在一個執(zhí)行Session的beginTransaction()方法后,就自動調(diào)用JDBC層的setAutoCommit(false)。如果想自己提供數(shù)據(jù)庫連接并使用自己的SQL語句,為了實現(xiàn)事務(wù),那么一開始就要把自動提交關(guān)掉(setAutoCommit(false)),并在事務(wù)結(jié)束時提交事務(wù)。

使用JDBC事務(wù)是進行事務(wù)管理最簡單的實現(xiàn)方式,Hibernate對于JDBC事務(wù)的封裝也很簡單。下面是一個在Hibernate中使用JDBC事務(wù)的例子:

try {

Session session = HibernateUtil.currentSession();

Transaction tx = session.beginTransaction(); //在默認情況下,開啟一個JDBC事物

for(int i=0; i<10; i++) {

   Student stu = new Student();

   stu.setName("Student" + i);

   session.save(stu);

}

   tx.commit(); //提交事務(wù)

   session.close();

} catch(Exception e) {…

tx.rollback();  //事務(wù)回滾

}

9.3.5 在Hibernate中使用JTA事務(wù)

JTA(Java Transaction API)是事務(wù)服務(wù)的J2EE解決方案。本質(zhì)上,它是描述事務(wù)接口的J2EE模型的一部分,開發(fā)人員直接使用該接口或者通過J2EE容器使用該接口來確保業(yè)務(wù)邏輯能夠可靠地運行。

JTA有3個接口,它們分別是UserTransaction接口、TransactionManager接口和Transaction接口。這些接口共享公共的事物操作,例如commit()和rollback(),但也包含特殊的事務(wù)操作,例如suspend()、resume()和enlist(),它們只出現(xiàn)在特定的接口上,以便在實現(xiàn)中允許一定程度的訪問控制。

在一個具有多個數(shù)據(jù)庫的系統(tǒng)中,可能一個程序會調(diào)用幾個數(shù)據(jù)庫中的數(shù)據(jù),需要一種分布式事務(wù),或者準備用JTA來管理跨Session的長事務(wù),那么就需要使用JTA事務(wù)。下面介紹如何在Hibernate的配置文件中配置JTA事務(wù)。在hibernate.properties文件中設(shè)置如下(把JTATransactionFactory所在的配置行的注釋符“#”取消掉):

hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory

# hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory

或者在hibernate.cfg.xml文件中配置如下:

<session-factory>

…..

<property name=” hibernate.transaction.factory_class”>

org.hibernate.transaction.JTATransactionFactory

</property>

……

</session-factory>

下面是一個應(yīng)用JTA事務(wù)的例子:

javax.transaction.UserTransaction tx = null;

tx = new initialContext().lookup(” javax.transaction.UserTransaction ”) ;

tx.begin();

Session s1 = sf.openSession();

……

s1.flush(); s1.close();

Session s2 = sf.openSession();

……

s2.flush(); s2.close();

tx.commit();

網(wǎng)站標題:hibernate事務(wù)-創(chuàng)新互聯(lián)
瀏覽地址:http://muchs.cn/article22/ioijc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、網(wǎng)站策劃、域名注冊、虛擬主機、品牌網(wǎng)站設(shè)計、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司