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