事務(wù)具備原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)4個(gè)屬性,簡(jiǎn)稱(chēng)ACID。下面對(duì)這4個(gè)特性分別進(jìn)行說(shuō)明。
l 原子性:將事務(wù)中所做的操作捆綁成一個(gè)原子單元,即對(duì)于事務(wù)所進(jìn)行的數(shù)據(jù)修改等操作,要么全部執(zhí)行,要么全部不執(zhí)行。
l 一致性:事務(wù)在完成時(shí),必須使所有的數(shù)據(jù)都保持一致?tīng)顟B(tài),而且在相關(guān)數(shù)據(jù)中,所有規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持所有數(shù)據(jù)的完整性。事務(wù)結(jié)束時(shí),所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)都應(yīng)該是正確的。
l 隔離性:由并發(fā)事務(wù)所做的修改必須與任何其他事務(wù)所做的修改相隔離。事務(wù)查看數(shù)據(jù)時(shí)數(shù)據(jù)所處的狀態(tài),要么是被另一并發(fā)事務(wù)修改之前的狀態(tài),要么是被另一并發(fā)事務(wù)修改之后的狀態(tài),即事務(wù)不會(huì)查看由另一個(gè)并發(fā)事務(wù)正在修改的數(shù)據(jù)。這種隔離方式也叫可串行性。
l 持久性:事務(wù)完成之后,它對(duì)系統(tǒng)的影響是永久的,即使出現(xiàn)系統(tǒng)故障也是如此。
9.3.2 事務(wù)隔離事務(wù)隔離意味著對(duì)于某一個(gè)正在運(yùn)行的事務(wù)來(lái)說(shuō),好像系統(tǒng)中只有這一個(gè)事務(wù),其他并發(fā)的事務(wù)都不存在一樣。在大部分情況下,很少使用完全隔離的事務(wù)。但不完全隔離的事務(wù)會(huì)帶來(lái)如下一些問(wèn)題。
l 更新丟失(Lost Update):兩個(gè)事務(wù)都企圖去更新一行數(shù)據(jù),導(dǎo)致事務(wù)拋出異常退出,兩個(gè)事務(wù)的更新都白費(fèi)了。
l 臟數(shù)據(jù)(Dirty Read):如果第二個(gè)應(yīng)用程序使用了第一個(gè)應(yīng)用程序修改過(guò)的數(shù)據(jù),而這個(gè)數(shù)據(jù)處于未提交狀態(tài),這時(shí)就會(huì)發(fā)生臟讀。第一個(gè)應(yīng)用程序隨后可能會(huì)請(qǐng)求回滾被修改的數(shù)據(jù),從而導(dǎo)致第二個(gè)事務(wù)使用的數(shù)據(jù)被損壞,即所謂的“變臟”。
l 不可重讀(Unrepeatable Read):一個(gè)事務(wù)兩次讀同一行數(shù)據(jù),可是這兩次讀到的數(shù)據(jù)不一樣,就叫不可重讀。如果一個(gè)事務(wù)在提交數(shù)據(jù)之前,另一個(gè)事務(wù)可以修改和刪除這些數(shù)據(jù),就會(huì)發(fā)生不可重讀。
l 幻讀(Phantom Read):一個(gè)事務(wù)執(zhí)行了兩次查詢(xún),發(fā)現(xiàn)第二次查詢(xún)結(jié)果比第一次查詢(xún)多出了一行,這可能是因?yàn)榱硪粋€(gè)事務(wù)在這兩次查詢(xún)之間插入了新行。
針對(duì)由事務(wù)的不完全隔離所引起的上述問(wèn)題,提出了一些隔離級(jí)別,用來(lái)防范這些問(wèn)題。
l 讀操作未提交(Read Uncommitted):說(shuō)明一個(gè)事務(wù)在提交前,其變化對(duì)于其他事務(wù)來(lái)說(shuō)是可見(jiàn)的。這樣臟讀、不可重讀和幻讀都是允許的。當(dāng)一個(gè)事務(wù)已經(jīng)寫(xiě)入一行數(shù)據(jù)但未提交,其他事務(wù)都不能再寫(xiě)入此行數(shù)據(jù);但是,任何事務(wù)都可以讀任何數(shù)據(jù)。這個(gè)隔離級(jí)別使用排寫(xiě)鎖實(shí)現(xiàn)。
l 讀操作已提交(Read Committed):讀取未提交的數(shù)據(jù)是不允許的,它使用臨時(shí)的共讀鎖和排寫(xiě)鎖實(shí)現(xiàn)。這種隔離級(jí)別不允許臟讀,但不可重讀和幻讀是允許的。
l 可重讀(Repeatable Read):說(shuō)明事務(wù)保證能夠再次讀取相同的數(shù)據(jù)而不會(huì)失敗。此隔離級(jí)別不允許臟讀和不可重讀,但幻讀會(huì)出現(xiàn)。
l 可串行化(Serializable):提供最嚴(yán)格的事務(wù)隔離。這個(gè)隔離級(jí)別不允許事務(wù)并行執(zhí)行,只允許串行執(zhí)行。這樣,臟讀、不可重讀或幻讀都可發(fā)生。
事務(wù)隔離與隔離級(jí)別的關(guān)系如表9-2所示。
表9-2 事務(wù)隔離與隔離級(jí)別的關(guān)系
隔 離 級(jí) 別
臟讀(Dirty Read)
不可重讀(Unrepeatable read)
幻讀(Phantom Read)
讀操作未提交(Read Uncommitted)
可能
可能
可能
讀操作已提交(Read Committed)
不可能
可能
可能
可重讀(Repeatable Read)
不可能
不可能
可能
可串行化(Serializable)
不可能
不可能
不可能
在一個(gè)實(shí)際應(yīng)用中,開(kāi)發(fā)者經(jīng)常不能確定使用什么樣的隔離級(jí)別。太嚴(yán)厲的級(jí)別將降低并發(fā)事務(wù)的性能,但是不足夠的隔離級(jí)別又會(huì)產(chǎn)生一些小的Bug,而這些Bug只會(huì)在系統(tǒng)重負(fù)荷(也就是并發(fā)嚴(yán)重時(shí))的情況下才會(huì)出現(xiàn)。
一般來(lái)說(shuō),讀操作未提交(Read Uncommitted)是很危險(xiǎn)的。一個(gè)事務(wù)的回滾或失敗都會(huì)影響到另一個(gè)并行的事務(wù),或者說(shuō)在內(nèi)存中留下和數(shù)據(jù)庫(kù)中不一致的數(shù)據(jù)。這些數(shù)據(jù)可能會(huì)被另一個(gè)事務(wù)讀取并提交到數(shù)據(jù)庫(kù)中。這是完全不允許的。
另外,大部分程序并不需要可串行化隔離(Serializable Isolation)。雖然,它不允許幻讀,但一般來(lái)說(shuō),幻讀并不是一個(gè)大問(wèn)題??纱谢綦x需要很大的系統(tǒng)開(kāi)支,很少有人在實(shí)際開(kāi)發(fā)中使用這種事務(wù)隔離模式。
現(xiàn)在留下來(lái)的可選的隔離級(jí)別是讀操作已提交(Read Committed)和可重讀(Repeatable Read)。Hibernate可以很好地支持可重讀(Repeatable Read)隔離級(jí)別。
9.3.3 在Hibernate配置文件中設(shè)置隔離級(jí)別JDBC連接數(shù)據(jù)庫(kù)使用的是默認(rèn)隔離級(jí)別,即讀操作已提交(Read Committed)和可重讀(Repeatable Read)。在Hibernate的配置文件hibernate.properties中,可以修改隔離級(jí)別:
#hibernate.connection.isolation 4
在上一行代碼中,Hibernate事務(wù)的隔離級(jí)別是4,這是什么意思呢?級(jí)別的數(shù)字意義如下。
l 1:讀操作未提交(Read Uncommitted)
l 2:讀操作已提交(Read Committed)
l 4:可重讀(Repeatable Read)
l 8:可串行化(Serializable)
因此,數(shù)字4表示“可重讀”隔離級(jí)別。如果要使以上語(yǔ)句有效,應(yīng)把此語(yǔ)句行前的注釋符“#”去掉:
hibernate.connection.isolation 4
也可以在配置文件hibernate.cfg.xml中加入以下代碼:
<session-factory>
…..
//把隔離級(jí)別設(shè)置為4
<property name=” hibernate.connection.isolation”>4</property>
……
</session-factory>
在開(kāi)始一個(gè)事務(wù)之前,Hibernate從配置文件中獲得隔離級(jí)別的值。
9.3.4 在Hibernate中使用JDBC事務(wù)Hibernate對(duì)JDBC進(jìn)行了輕量級(jí)的封裝,它本身在設(shè)計(jì)時(shí)并不具備事務(wù)處理功能。Hibernate將底層的JDBCTransaction或JTATransaction進(jìn)行了封裝,再在外面套上Transaction和Session的外殼,其實(shí)是通過(guò)委托底層的JDBC或JTA來(lái)實(shí)現(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ù)工廠類(lèi)可以設(shè)置成JDBCTransactionFactory或者JTATransactionFactory。如果不進(jìn)行配置,Hibernate就會(huì)認(rèn)為系統(tǒng)使用的事務(wù)是JDBC事務(wù)。
在JDBC的提交模式(commit mode)中,如果數(shù)據(jù)庫(kù)連接是自動(dòng)提交模式(auto commit mode),那么在每一條SQL語(yǔ)句執(zhí)行后事務(wù)都將被提交,提交后如果還有任務(wù),那么一個(gè)新的事務(wù)又開(kāi)始了。
Hibernate在Session控制下,在取得數(shù)據(jù)庫(kù)連接后,就立刻取消自動(dòng)提交模式,即Hibernate在一個(gè)執(zhí)行Session的beginTransaction()方法后,就自動(dòng)調(diào)用JDBC層的setAutoCommit(false)。如果想自己提供數(shù)據(jù)庫(kù)連接并使用自己的SQL語(yǔ)句,為了實(shí)現(xiàn)事務(wù),那么一開(kāi)始就要把自動(dòng)提交關(guān)掉(setAutoCommit(false)),并在事務(wù)結(jié)束時(shí)提交事務(wù)。
使用JDBC事務(wù)是進(jìn)行事務(wù)管理最簡(jiǎn)單的實(shí)現(xiàn)方式,Hibernate對(duì)于JDBC事務(wù)的封裝也很簡(jiǎn)單。下面是一個(gè)在Hibernate中使用JDBC事務(wù)的例子:
try {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction(); //在默認(rèn)情況下,開(kāi)啟一個(gè)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模型的一部分,開(kāi)發(fā)人員直接使用該接口或者通過(guò)J2EE容器使用該接口來(lái)確保業(yè)務(wù)邏輯能夠可靠地運(yùn)行。
JTA有3個(gè)接口,它們分別是UserTransaction接口、TransactionManager接口和Transaction接口。這些接口共享公共的事物操作,例如commit()和rollback(),但也包含特殊的事務(wù)操作,例如suspend()、resume()和enlist(),它們只出現(xiàn)在特定的接口上,以便在實(shí)現(xiàn)中允許一定程度的訪問(wèn)控制。
在一個(gè)具有多個(gè)數(shù)據(jù)庫(kù)的系統(tǒng)中,可能一個(gè)程序會(huì)調(diào)用幾個(gè)數(shù)據(jù)庫(kù)中的數(shù)據(jù),需要一種分布式事務(wù),或者準(zhǔn)備用JTA來(lái)管理跨Session的長(zhǎng)事務(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>
下面是一個(gè)應(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)站標(biāo)題:hibernate事務(wù)-創(chuàng)新互聯(lián)
瀏覽地址:http://chinadenli.net/article22/ioijc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、網(wǎng)站策劃、域名注冊(cè)、虛擬主機(jī)、品牌網(wǎng)站設(shè)計(jì)、做網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容