1. 程式人生 > >Spring架構---Spring中的事務管理詳解

Spring架構---Spring中的事務管理詳解

Spring中的事務管理詳解

1. 事務簡介:

事務管理是企業級應用程式開發中必不可少的技術,用來確保資料的完整性和一致性

事務就是一系列的動作,它們被當作一個單獨的工作單元。這些動作要麼全部完成,要麼全部不起作用

2. 事務的四個關鍵屬性(ACID)

① 原子性(atomicity):事務是一個原子操作,有一系列動作組成。事務的原子性確保動作要麼全部完成,要麼完全不起作用
② 一致性(consistency):一旦所有事務動作完成,事務就被提交。資料和資源就處於一種滿足業務規則的一致性狀態中
③ 隔離性(isolation):可能有許多事務會同時處理相同的資料,因此每個事物都應該與其他事務隔離開來,防止資料損壞
④ 永續性(durability):一旦事務完成,無論發生什麼系統錯誤,它的結果都不應該受到影響。通常情況下,事務的結果被寫到持久化儲存器中

3. Spring中的事務管理

作為企業級應用程式框架,Spring在不同的事務管理API之上定義了一個抽象層。而應用程式開發人員不必瞭解底層的事務管理API,就可以使用Spring的事務管理機制。

Spring既支援程式設計式事務管理(也稱編碼式事務),也支援宣告式的事務管理

程式設計式事務管理:將事務管理程式碼嵌入到業務方法中來控制事務的提交和回滾,在程式設計式事務中,必須在每個業務操作中包含額外的事務管理程式碼

宣告式事務管理:大多數情況下比程式設計式事務管理更好用。它將事務管理程式碼從業務方法中分離出來,以宣告的方式來實現事務管理。事務管理作為一種橫切關注點,可以通過AOP方法模組化。Spring通過Spring AOP框架支援宣告式事務管理。

4. Spring的事務管理器 

pring並不直接管理事務,而是提供了多種事務管理器,它們將事務管理的職責委託給JTA或其他持久化機制所提供的平臺相關的事務實現。每個事務管理器都會充當某一特定平臺的事務實現的門面,這使得使用者在Spring中使用事務時,幾乎不用關注實際的事務實現是什麼。

Spring提供了許多內建事務管理器實現:

 Spring為不同的持久化框架提供了不同的Platform TransactionManager介面實現。如:

        使用Spring JDBC或iBatis進行持久化資料時使用DataSourceTransactionManager

        使用Hibernate3.0版本進行持久化資料時使用HibernateTransactionManager(這裡不再過多例舉)

接下來讓我們學習一下如何在Spring配置檔案中定義事務管理器:

宣告對本地事務的支援:

a)JDBC及iBATIS、MyBatis框架事務管理器

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

 通過dataSource屬性指定需要事務管理的單個javax.sql.DataSource物件。在幕後DataSourceTransactionManager通過呼叫java.sql.Connection來管理事務,而後者是通過DataSource獲取到的。通過呼叫連線的commit()方法來提交事務。同樣,事務失敗時通過呼叫rollback()方法進行回滾。

 

b)Hibernate事務管理器

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

在幕後HibernateTransactionManager將事務管理的職責委託給org.hibernate.Transaction物件,而後者是從Hibernate Session中獲取到的。當事務成功完成時,HibernateTransactionManager將會呼叫Transaction物件的commit()方法來提交事務。同樣,事務失敗時通過呼叫Transaction的rollback()方法進行回滾。

 

5. Spring事務屬性

在Spring中,宣告式事務是通過事務屬性來定義的,事務屬性描述了事務策略如何應用到方法上。事務屬性包含了5個方面,儘管Spring提供了多種宣告式事務的機制,但是所有的方式都依賴這五個引數來控制如何管理事務策略。宣告式事務通過傳播行為,隔離級別,只讀提示,事務超時及回滾規則來進行定義。

(1)Spring事務的傳播行為:

當事務方法被另一個事務方法呼叫時,必須指定事務應該如何傳播。例如:方法可能繼續在現有事務中執行,也可能開啟一個新事務,並在自己的事務中執行。

事務的傳播行為可以由傳播屬性指定。Spring定義了7種傳播行為:

Spring支援的事務傳播行為
傳播行為 含義
PROPAGATION_MANDATORY 表示該方法必須在事務中執行,如果當前事務不存在,則會丟擲一個異常
PROPAGATION_NESTED 表示如果當前已經存在一個事務,那麼該方法將會在巢狀事務中執行。巢狀的事務可以獨立於當前事務進行單獨地提交或回滾。如果當前事務不存在,那麼其行為與PROPAGATION_REQUIRED一樣。注意各廠商對這種傳播行為的支援是有所差異的。可以參考資源管理器的文件來確認它們是否支援巢狀事務
PROPAGATION_NEVER   表示當前方法不應該執行在事務上下文中。如果當前正有一個事務在執行,則會丟擲異常
PROPAGATION_NOT_SUPPORTED 表示該方法不應該執行在事務中。如果存在當前事務,在該方法執行期間,當前事務將被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager
PROPAGATION_REQUIRED 表示當前方法必須執行在事務中。如果當前事務存在,方法將會在該事務中執行。否則,會啟動一個新的事務
PROPAGATION_REQUIRED_NEW 表示當前方法必須執行在它自己的事務中。一個新的事務將被啟動。如果存在當前事務,在該方法執行期間,當前事務會被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager
PROPAGATION_SUPPORTS 表示當前方法不需要事務上下文,但是如果存在當前事務的話,那麼該方法會在這個事務中執行

其中PROPAGATION_REQUIRED為預設的傳播屬性

(2)Spring事務的隔離級別

隔離級別定義了一個事務可能受其他併發事務影響的程度。在典型的應用程式中,多個事務併發執行,經常會操作相同的資料來完成各自的任務。併發,雖然是必須的,可是會導致下面的問題。

 併發事務所導致的問題可以分為以下三類:

        髒讀:一個事務讀取了另一個事務改寫但還未提交的資料,如果這些資料被回滾,則讀到的資料是無效的。

        不可重複讀:在同一事務中,多次讀取同一資料返回的結果有所不同。

        幻讀:一個事務讀取了幾行記錄後,另一個事務插入一些記錄,幻讀就發生了。再後來的查詢中,第一個事務就會發現有些原來沒有的記錄。

 事務隔離級別:(五種)

  •  DEFAULT--使用後端資料庫預設的隔離級別(Spring中的選擇項)
  •     READ_UNCOMMITED--允許你讀取還未提交的改變了的資料。可能導致髒、幻、不可重複讀
  •     READ_COMMITTED--允許在併發事務已經提交後讀取。可防止髒讀,但幻讀和不可重複讀仍可發生
  •     REPEATABLE_READ--對相同欄位的多次讀取是一致的,除非資料被事務本身改變。可防止髒、不可重複讀,但幻讀仍可能發生
  •     SERIALIZABLE--完全服從ACID的隔離級別,確保不發生髒、幻、不可重複讀。這在所有的隔離級別中是最慢的,它是典型的通過完全鎖定在事務中涉及的資料表來完成的

    其中,MySQL預設採用REPEATABLE_READ隔離級別;Oracle預設採用READ_COMMITTED隔離級別

(4)Spring事務的事務超時

為了使應用程式更好的執行,事務不能執行太長的時間。因此,宣告式事務的第四個特性就是超時。

(5)Spring事務的回滾規則

預設情況下,事務只有在遇到執行期異常時才會回滾,而在遇到檢查型異常時不會回滾,但是也可以宣告事務在遇到特定的檢查型異常時像遇到執行期異常那樣回滾。同樣,你還可以宣告事務遇到特定的異常不回滾,即使這些異常是執行期異常。

(6)Spring事務的只讀

“只讀事務”並不是一個強制選項,它只是一個“暗示”,提示資料庫驅動程式和資料庫系統,這個事務並不包含更改資料的操作,那麼JDBC驅動程式和資料庫就有可能根據這種情況對該事務進行一些特定的優化,比方說不安排相應的資料庫鎖,以減輕事務對資料庫的壓力,畢竟事務也是要消耗資料庫的資源的。“只讀事務”僅僅是一個性能優化的推薦配置而已,並非強制你要這樣做不可。