Spring事務的架構 .

Spring的事務框架設計理念的基本原則是:讓事務管理的關注點與數據訪問關注點相分離。從此之後,事務管理就是事務管理,數據訪問只關心數據訪問,再也不用因爲它們之間的糾纏而煩惱

 

org.springframework.transaction.PlatformTransactionManager是Spring事務抽象架構的核心接口,它的主要作用是爲應用程序提供事務界定的統一方式。既然事務界定的需要很簡單,那麼PlatformTransactionManager的定義看起來也不會過於複雜.

PlatformTransactionManager是整個事務抽象策略的頂層接口,它就好像我們的戰略藍圖,而戰略的具體實施則將由相應的PlatformTransactionManager實現類來執行

Spring的事務框架針對不同的數據訪問方式以及全局事務場景,提供了相應的Platform- TransactionManager實現類。在每個實現類的職責完成之後,Spring事務框架的"統一大業"就完成了。在深入瞭解各個PlatformTransactionManager實現類的奧祕之前,不妨先考慮一下,如果讓我們來實現一個PlatformTransactionManager,要如何去做?

 

我們通常都是將事務管理放在Service層,而將數據訪問邏輯放在DAO層。這樣做的目的是,可以不用因爲將事務管理代碼放在DAO層,而降低數據訪問邏輯的重用性,也可以在Service層根據相應邏輯,來決定提交或者回滾事務。一般的Service對象可能需要在同一個業務方法中調用多個數據訪問對象的方法

 對於我們要實現的針對JDBC的PlatformTransactionManager,只需要在事務開始的時候,通過我們的TransactionResourceManager將java.sql.Connection綁定到線程,然後在事務結束的時候解除綁定即可

 

Spring的事務抽象包括3個主要接口,即PlatformTransactionManager、TransactionDefinition以及TransactionStatus,

這3個接口以org.springframe- work.transaction.PlatformTran- sactionManager爲中心,互爲犄角,多少有點兒"晉西北鐵三角"的味道。

org.springframework.transac- tion.PlatformTransactionManager負責界定事務邊界。

org.spring- framework.transaction.TransactionDefinition負責定義事務相關屬性,包括隔離級別、傳播行爲等。org.springframework.transaction.PlatformTransactionManager將參照org.springframe- work.transaction.TransactionDefinition的屬性定義來開啓相關事務。

事務開啓之後到事務結束期間的事務狀態由org.springframework.transaction.TransactionStatus負責,

我們也可以通過org.springframework.transaction.TransactionStatus對事務進行有限的控制

 

1. TransactionDefinition簡介

org.springframework.transaction.TransactionDefinition主要定義了有哪些事務屬性可以指定,這包括:

事務的隔離(Isolation)級別

事務的傳播行爲(Propagation Behavior)

事務的超時時間(Timeout)

是否爲只讀(ReadOnly)事務

TransactionDefinition內定義瞭如下5個常量用於標誌可供選擇的隔離級別。

ISOLATION_DEFAULT。如果指定隔離級別爲ISOLATION_DEFAULT,則表示使用數據庫默認的隔離級別,通常情況下是Read Committed。

ISOLATION_READ_UNCOMMITTED。對應Read Uncommitted隔離級別,無法避免髒讀,不可重複讀和幻讀。

ISOLATION_READ_COMMITTED。對應Read Committed隔離級別,可以避免髒讀,但無法避免不可重複讀和幻讀。

ISOLATION_REPEATABLE_READ。對應Repeatable read隔離級別,可以避免髒讀和不可重複讀,但不能避免幻讀。

ISOLATION_SERIALIZABLE。對應Serializable隔離級別,可以避免所有的髒讀,不可重複讀以及幻讀,但併發性效率最低。

 

 

針對事務的傳播行爲,TransactionDefinition提供了以下幾種選擇,除了PROPAGATION_ NESTED是Spring特有的外,其他傳播行爲的語義與CMT基本相同。

PROPAGATION_REQUIRED。如果當前存在一個事務,則加入當前事務。如果不存在任何事務,則創建一個新的事務。總之,要至少保證在一個事務中運行。

PROPAGATION_REQUIRED通常作爲默認的事務傳播行爲。

PROPAGATION_SUPPORTS。如果當前存在一個事務,則加入當前事務。如果當前不存在事務,則直接執行。對於一些查詢方法來說,PROPAGATION_SUPPORTS通常是比較合適的傳播行爲選擇。如果當前方法直接執行,那麼不需要事務的支持。如果當前方法被其他方法調用,而其他方法啓動了一個事務,使用PROPAGATION_SUPPORTS可以保證當前方法能夠加入當前事務,並洞察當前事務對數據資源所做的更新。比如,A.service()會首先更新數據庫,然後調用B.service()進行查詢,那麼,如果B.service()是

PROPAGATION_SUPPORTS的傳播行爲,就可以讀取A.service()之前所做的最新更新結果(如圖19-6所示)。而如果使用稍後所提到的

PROPAGATION_NOT_SUPPORTED,則B.service()將無法讀取最新的更新結果,因爲A.service()的事務在這時還沒有提交(除非隔離級別是Read Uncommitted)。

PROPAGATION_MANDATORY。PROPAGATION_MANDATORY強制要求當前存在一個事務,如果不存在,則拋出異常。如果某個方法需要事務支持,但自身又不管理事務提交或者回滾,那麼比較適合使用PROPAGATION_MANDATORY。可以參照Java Transaction Design Strategies一書中對REQUIRED和MANDATORY兩種傳播行爲的比較,來更深入地瞭解PROPAGATION_ MANDATORY可能的應用場景。

 

PROPAGATION_REQUIRES_NEW。不管當前是否存在事務,都會創建新的事務。如果當前存在事務,會將當前的事務掛起(Suspend)。如果某個業務對象所做的事情不想影響到外層事務,PROPAGATION_REQUIRES_NEW應該是合適的選擇。比如,假設當前的業務方法需要向數據庫中更新某些日誌信息,但即使這些日誌信息更新失敗,我們也不想因爲該業務方法的事務回滾,而影響到外層事務的成功提交。因爲這種情況下,當前業務方法的事務成功與否對外層事務來說是無關緊要的。

PROPAGATION_NOT_SUPPORTED。不支持當前事務,而是在沒有事務的情況下執行。如果當前存在事務的話,當前事務原則上將被掛起(Suspend),但這要看對應的PlatformTransaction- Manager實現類是否支持事務的掛起。更多情況請參照TransactionDefinition的Javadoc文檔。PROPAGATION_NOT_SUPPORTED與

PROPAGATION_SUPPORTS之間的區別,可以參照PROPAGATION_ SUPPORTS部分的實例內容。

PROPAGATION_NEVER。永遠不需要當前存在事務,如果存在當前事務,則拋出異常。

PROPAGATION_NESTED。如果存在當前事務,則在當前事務的一個嵌套事務中執行,否則與PRO- PAGATION_REQUIRED的行爲類似,即創建新的事務,在新創建的事務中執行。PROPAGATION_ NESTED粗看起來好像與PROPAGATION_REQUIRES_NEW的行爲類似,實際上二者是有差別的。PROPAGATION_REQUIRES_NEW創建的新事務與外層事務屬於同一個"檔次",即二者的地位是相同的。當新創建的事務運行的時候,外層事務將被暫時掛起。而PROPAGATION_NESTED創建的嵌套事務則不然,它是寄生於當前外層事務的,它的地位比當前外層事務的地位要小一號。當內部嵌套事務運行的時候,外層事務也是處於active狀態,圖19-7演示了PROPAGATION_

REQUIRES_NEW和PROPAGATION_NESTED中涉及的多個事務相互之間的地位。

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