在軟件中,要么全有要么全無(wú)的操作成為事務(wù)。事務(wù)允許你把幾個(gè)操作組成一個(gè)單一的工作單元,這個(gè)工作單元要么全部發(fā)生要么全部不發(fā)生。如果每件事都順利,那么這個(gè)事務(wù)是成功的。但是如果任何一件事情出錯(cuò)的話,那么已經(jīng)發(fā)生的行為就被清除掉,就像什么事情都沒(méi)發(fā)生一樣。
Spring對(duì)事務(wù)管理有豐富的支持,程序控制的和聲明式的。
原子性(Atomic):事務(wù)由一個(gè)或多個(gè)行為綁定在一起組成,好像是一個(gè)單獨(dú)工作單元。原子性確保在十五中的所有操作要么都發(fā)生,要么都不發(fā)生。
一致性(Consistent):一旦一個(gè)事務(wù)結(jié)束了(不管成功失敗),系統(tǒng)所處的狀態(tài)和它的業(yè)務(wù)規(guī)則是一致的。就是說(shuō)數(shù)據(jù)應(yīng)當(dāng)不會(huì)被破壞。
隔離性(Isolated):事務(wù)應(yīng)該允許多個(gè)用戶操作同一數(shù)據(jù),一個(gè)用戶的操作不會(huì)和其他用戶的操作相混淆。因此,事務(wù)必須是互相隔離的,防止并發(fā)讀寫同一數(shù)據(jù)的情況發(fā)生。
持久性(Durable):一旦事務(wù)完成,事務(wù)的結(jié)果應(yīng)該持久化,這樣不管什么樣的系統(tǒng)崩潰,他們都將幸免于難。
Spring對(duì)程序控制事務(wù)管理的支持和EJB的有很大不同。EJB的事務(wù)管理和JTA密不可分,和EJB不同的是,Spring使用了一種回調(diào)機(jī)制,把真實(shí)的事務(wù)實(shí)現(xiàn)從事務(wù)代碼中抽象出來(lái)。選擇程序控制事務(wù)管理還是聲明式事務(wù)管理,很大程度上是在細(xì)粒度控制與簡(jiǎn)便操作之間做出決定。當(dāng)你在代碼中編寫事務(wù)時(shí),你能精確控制事務(wù)的邊界,在你希望的地方精確的開始和結(jié)束。典型的情況下,你不需要程序控制事務(wù)所提供的細(xì)粒度控制,你會(huì)選擇在上下文定義文件中聲明你的事務(wù)。
Spring對(duì)聲明式事務(wù)管理的支持是通過(guò)它的AOP框架實(shí)現(xiàn)的。這樣做是非常自然的,因?yàn)槭聞?wù)是系統(tǒng)級(jí)的,凌駕于應(yīng)用的主要功能之上的。
在Spring里,事務(wù)屬性是對(duì)事務(wù)策略如何應(yīng)用到方法的描述。這個(gè)描述包括:傳播行為、隔離級(jí)別、只讀提示、事務(wù)超時(shí)間隔
傳播行為:
PROPAGATION_MANDATORY:表示該方法必須運(yùn)行在一個(gè)事務(wù)中。如果當(dāng)前事務(wù)不存在,將拋出一個(gè)異常。
PROPAGATION_NESTED:表示如果當(dāng)前已經(jīng)存在一個(gè)事務(wù),則該方法應(yīng)當(dāng)運(yùn)行在一個(gè)嵌套的事務(wù)中。被嵌套的事務(wù)可以從當(dāng)前事務(wù)中單獨(dú)的提交或回滾。如果當(dāng)前事務(wù)不存在,那么它看起來(lái)和PROPAGATION_REQUIRED沒(méi)有兩樣。
PROPAGATION_NEVER:表示當(dāng)前的方法不應(yīng)該運(yùn)行在一個(gè)事務(wù)上下文中。如果當(dāng)前存在一個(gè)事務(wù),則會(huì)拋出一個(gè)異常。
PROPAGATION_NOT_SUPPORTED:表示該方法不應(yīng)在事務(wù)中運(yùn)行。如果一個(gè)現(xiàn)有的事務(wù)正在運(yùn)行中,它將在該方法的運(yùn)行期間被掛起。
PROPAGATION_REQUIRED:表示當(dāng)前方法必須運(yùn)行在一個(gè)事務(wù)中。如果一個(gè)現(xiàn)有的事務(wù)正在運(yùn)行中,該方法將運(yùn)行在這個(gè)事務(wù)中。否則的話,要開始一個(gè)新的事務(wù)。
PROPAGATION_REQUIRES_NEW:表示當(dāng)前方法必須運(yùn)行在它自己的事務(wù)里。它將啟動(dòng)一個(gè)新的事務(wù)。如果有事務(wù)運(yùn)行的話,將在這個(gè)方法運(yùn)行期間被掛起。
PROPAGATION_SUPPORTS:表示當(dāng)前方法不需要事務(wù)處理環(huán)境,但如果有一個(gè)事務(wù)已經(jīng)在運(yùn)行的話,這個(gè)方法也可以在這個(gè)事務(wù)里運(yùn)行。
傳播規(guī)則回答了一個(gè)問(wèn)題:就是新的事務(wù)是否要被啟動(dòng)或是被掛起,或者方法是否要在事務(wù)環(huán)境中運(yùn)行。
隔離級(jí)別:在一個(gè)典型的應(yīng)用中,多個(gè)事務(wù)并發(fā)運(yùn)行,經(jīng)常會(huì)操作同一個(gè)數(shù)據(jù)來(lái)完成它們的任務(wù)。并發(fā),雖然是必須的,但會(huì)導(dǎo)致下面問(wèn)題:
1、臟讀:臟讀發(fā)生在一個(gè)事務(wù)讀取了被另一個(gè)事務(wù)改寫但還未提交的數(shù)據(jù)時(shí)。如果這些改變?cè)谏院蟊换貪L,那么第一個(gè)事務(wù)讀取的數(shù)據(jù)就是無(wú)效的。
2、不可重復(fù)讀:不可重復(fù)讀發(fā)生在一個(gè)事務(wù)執(zhí)行相同的查詢2次或2次以上,但每一次查詢結(jié)果都不同時(shí)。這通常是由于另一個(gè)并發(fā)事務(wù)在2次查詢之間更新了數(shù)據(jù)。
3、幻讀:幻讀和不可重復(fù)讀相似。當(dāng)一個(gè)事務(wù)讀取幾行紀(jì)錄后,另一個(gè)并發(fā)事務(wù)插入一些記錄,幻讀就發(fā)生了。隔離級(jí)別有如下幾個(gè):
ISOLATION_DEFAULT:使用后端數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別
ISOLATION_READ_UNCOMMITTED:允許你讀取還未提交的改變了的數(shù)據(jù),可能導(dǎo)致臟讀、幻讀、不可重復(fù)讀
ISOLATION_READ_COMMITTED:允許在并發(fā)事務(wù)已經(jīng)提交后讀取。可防止臟讀,但幻讀和不可重復(fù)讀仍可能發(fā)生。
ISOLATION_REPEATABLE_READ:對(duì)相同字段的多次讀取的結(jié)果是一致的,除非數(shù)據(jù)被事務(wù)本身改變。可防止臟讀和不可重復(fù)讀,但幻讀仍可能發(fā)生。
ISOLATION_SERIALIZABLE:完全服從ACID的隔離級(jí)別,確保不發(fā)生臟讀、不可重復(fù)讀和幻讀。這在所有隔離級(jí)別中也是最慢的。
只讀:如果一個(gè)事務(wù)只對(duì)后端是據(jù)庫(kù)執(zhí)行讀操作,數(shù)據(jù)庫(kù)就可能利用事務(wù)只讀的特性,使用某些優(yōu)化措施。通過(guò)聲明一個(gè)事務(wù)為只讀,你就給了后端數(shù)據(jù)庫(kù)一個(gè)機(jī)會(huì),來(lái)應(yīng)用那些它認(rèn)為合適的優(yōu)化措施。因?yàn)橹蛔x的優(yōu)化措施是在事務(wù)啟動(dòng)時(shí)由后端數(shù)據(jù)庫(kù)實(shí)施的,所以,只有將那些具有可能啟動(dòng)新事務(wù)的傳播行為的方法的事務(wù)標(biāo)記成只讀才有意義(PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED) TransactionProxyFactoryBean參照一個(gè)方法的事務(wù)屬性,決定如何在那個(gè)方法上執(zhí)行事務(wù)策略。




























































除了將transactionAttributeSource對(duì)象織入到TransactionProxyFactoryBean的transactionAttributeSource屬性中外,還有一種簡(jiǎn)單的方法。發(fā)展到現(xiàn)在,TransactionProxyFactoryBean也有一個(gè)transactionAttributes屬性為transactionProperties.























































