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