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驅動程序和數據庫就有可能根據這種情況對該事務進行一些特定的優化,比方說不安排相應的數據庫鎖,以減輕事務對數據庫的壓力,畢竟事務也是要消耗數據庫的資源的。“只讀事務”僅僅是一個性能優化的推薦配置而已,並非強制你要這樣做不可。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章