Spring中的事務管理詳解
在這裡主要介紹Spring對事務管理的一些理論知識,實戰方面參考上一篇博文:
http://www.cnblogs.com/longshiyVip/p/5061547.html
1. 事務簡介:
事務管理是企業級應用程式開發中必不可少的技術,用來確保資料的完整性和一致性
事務就是一系列的動作,它們被當作一個單獨的工作單元。這些動作要麼全部完成,要麼全部不起作用
2. 事務的四個關鍵屬性(ACID)
① 原子性(atomicity):事務是一個原子操作,有一系列動作組成。事務的原子性確保動作要麼全部完成,要麼完全不起作用
② 一致性(consistency):一旦所有事務動作完成,事務就被提交。資料和資源就處於一種滿足業務規則的一致性狀態中
③ 隔離性(isolation):可能有許多事務會同時處理相同的資料,因此每個事物都應該與其他事務隔離開來,防止資料損壞
④ 永續性(durability):一旦事務完成,無論發生什麼系統錯誤,它的結果都不應該受到影響。通常情況下,事務的結果被寫到持久化儲存器中
3. Spring中的事務管理
作為企業級應用程式框架,Spring在不同的事務管理API之上定義了一個抽象層。而應用程式開發人員不必瞭解底層的事務管理API,就可以使用Spring的事務管理機制。
Spring既支援程式設計式事務管理(也稱編碼式事務),也支援宣告式的事務管理
程式設計式事務管理:將事務管理程式碼嵌入到業務方法中來控制事務的提交和回滾,在程式設計式事務中,必須在每個業務操作中包含額外的事務管理程式碼
宣告式事務管理:大多數情況下比程式設計式事務管理更好用。它將事務管理程式碼從業務方法中分離出來,以宣告的方式來實現事務管理。事務管理作為一種橫切關注點,可以通過AOP方法模組化。Spring通過Spring AOP框架支援宣告式事務管理。
4. Spring的事務管理器
Spring並不直接管理事務,而是提供了多種事務管理器,它們將事務管理的職責委託給JTA或其他持久化機制所提供的平臺相關的事務實現。每個事務管理器都會充當某一特定平臺的事務實現的門面,這使得使用者在Spring中使用事務時,幾乎不用關注實際的事務實現是什麼。
Spring提供了許多內建事務管理器實現:
● DataSourceTransactionManager: 位於org.springframework.jdbc.datasource包中,資料來源事務管理器,提供對單個javax.sql.DataSource事務管理,用於Spring JDBC抽象框架、iBATIS或MyBatis框架的事務管理;
● JdoTransactionManager: 位於org.springframework.orm.jdo包中,提供對單個javax.jdo.PersistenceManagerFactory事務管理,用於整合JDO框架時的事務管理;
● JpaTransactionManager: 位於org.springframework.orm.jpa包中,提供對單個javax.persistence.EntityManagerFactory事務支援,用於整合JPA實現框架時的事務管理;
● HibernateTransactionManager: 位於org.springframework.orm.hibernate3包中,提供對單個org.hibernate.SessionFactory事務支援,用於整合Hibernate框架時的事務管理;該事務管理器只支援Hibernate3+版本,且Spring3.0+版本只支援Hibernate 3.2+版本;
● JtaTransactionManager: 位於org.springframework.transaction.jta包中,提供對分散式事務管理的支援,並將事務管理委託給Java EE應用伺服器事務管理器;
● OC4JjtaTransactionManager: 位於org.springframework.transaction.jta包中,Spring提供的對OC4J10.1.3+應用伺服器事務管理器的介面卡,此介面卡用於對應用伺服器提供的高階事務的支援;
● WebSphereUowTransactionManager: 位於org.springframework.transaction.jta包中,Spring提供的對WebSphere 6.0+應用伺服器事務管理器的介面卡,此介面卡用於對應用伺服器提供的高階事務的支援;
● WebLogicJtaTransactionManager: 位於org.springframework.transaction.jta包中,Spring提供的對WebLogic 8.1+應用伺服器事務管理器的介面卡,此介面卡用於對應用伺服器提供的高階事務的支援。
Spring不僅提供這些事務管理器,還提供對如JMS事務管理的管理器等,Spring提供一致的事務抽象如圖9-1所示。
圖9-1 Spring事務管理器
接下來讓我們學習一下如何在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)Jdo 事務管理器
<bean id="txManager" class="org.springframework.orm.jdo.JdoTransactionManager"> <property name="persistenceManagerFactory" ref="persistenceManagerFactory"/></bean>
通過persistenceManagerFactory屬性指定需要事務管理的javax.jdo.PersistenceManagerFactory物件。
c)Jpa 事務管理器
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/></bean>
通過entityManagerFactory屬性指定需要事務管理的javax.persistence.EntityManagerFactory物件。
還需要為entityManagerFactory物件指定jpaDialect屬性,該屬性所對應的物件指定了如何獲取連線物件、開啟事務、關閉事務等事務管理相關的行為。
< bean id ="entityManagerFactory" class ="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
…… < property name ="jpaDialect" ref ="jpaDialect" /> </ bean > < bean id ="jpaDialect" class ="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
d)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()方法進行回滾。
Spring對全域性事務的支援:
a)Jta事務管理器
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee ="http://www.springframework.org/schema/jee"
xsi:schemaLocation ="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd" > < jee:jndi-lookup id ="dataSource" jndi-name ="jdbc/test" /> < bean id ="txManager" class ="org.springframework.transaction.jta.JtaTransactionManager" > < property name ="transactionManagerName" value =" java:comp/TransactionManager" /> </ bean > </ beans >
“dataSource”Bean表示從JNDI中獲取的資料來源,而txManager是JTA事務管理器,其中屬性transactionManagerName指定了JTA事務管理器的JNDI名字,從而將事務管理委託給該事務管理器。
5. 定義事務屬性
在Spring中,宣告式事務是通過事務屬性來定義的,事務屬性描述了事務策略如何應用到方法上。事務屬性包含了5個方面,儘管Spring提供了多種宣告式事務的機制,但是所有的方式都依賴這五個引數來控制如何管理事務策略。宣告式事務通過傳播行為,隔離級別,只讀提示,事務超時及回滾規則 來進行定義。
Spring事務的傳播行為:
當事務方法被另一個事務方法呼叫時,必須指定事務應該如何傳播。例如:方法可能繼續在現有事務中執行,也可能開啟一個新事務,並在自己的事務中執行。
事務的傳播行為可以由傳播屬性指定。Spring定義了7種傳播行為:
傳播行為 | 含義 |
PROPAGATION_MANDATORY | 表示該方法必須在事務中執行,如果當前事務不存在,則會丟擲一個異常 |
PROPAGATION_NESTED | 表示如果當前已經存在一個事務,那麼該方法將會在巢狀事務中執行。巢狀的事務可以獨立於當前事務進行單獨地提交或回滾。如果當前事務不存在,那麼其行為與PROPAGATION_REQUIRED一樣。注意各廠商對這種傳播行為的支援是有所差異的。可以參考資源管理器的文件來確認它們是否支援巢狀事務 |
PROPAGATION_NEVER | 表示當前方法不應該執行在事務上下文中。如果當前正有一個事務在執行,則會丟擲異常 |
PROPAGATION_NOT_SUPPORTED | 表示該方法不應該執行在事務中。如果存在當前事務,在該方法執行期間,當前事務將被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager |
PROPAGATION_REQUIRED | 表示當前方法必須執行在事務中。如果當前事務存在,方法將會在該事務中執行。否則,會啟動一個新的事務 |
PROPAGATION_REQUIRED_NEW | 表示當前方法必須執行在它自己的事務中。一個新的事務將被啟動。如果存在當前事務,在該方法執行期間,當前事務會被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager |
PROPAGATION_SUPPORTS | 表示當前方法不需要事務上下文,但是如果存在當前事務的話,那麼該方法會在這個事務中執行 |
其中PROPAGATION_REQUIRED為預設的傳播屬性
Spring事務的隔離級別
隔離級別定義了一個事務可能受其他併發事務影響的程度。在典型的應用程式中,多個事務併發執行,經常會操作相同的資料來完成各自的任務。併發,雖然是必須的,可是會導致下面的問題。
併發事務所導致的問題可以分為以下三類:
①髒讀(Dirty reads) :髒讀發生在一個事務讀取了另一個事務改寫但尚未提交的資料時。如果改寫在稍後被回滾了,那麼第一個事務獲取的資料就是無效的。
②不可重複讀(Nonrepeatable read) :不可重複讀發生在一個事務執行相同的查詢兩次或兩次以上,但是每次都得到不同的資料時。這通常是因為另一個併發事務在兩次查詢期間更新了資料
③幻讀(Phantom read) :幻讀與不可重複讀類似。它發生在一個事務(T1)讀取了幾行資料,接著另一個併發事務(T2)插入了一些資料時。在隨後的查詢中,第一個事務(T1)就會發現多了一些原本不存在的記錄
Spring事務的隔離級別
1. ISOLATION_DEFAULT: 這是一個PlatfromTransactionManager預設的隔離級別,使用資料庫預設的事務隔離級別.
另外四個與JDBC的隔離級別相對應
2. ISOLATION_READ_UNCOMMITTED: 這是事務最低的隔離級別,它充許令外一個事務可以看到這個事務未提交的資料。
這種隔離級別會產生髒讀,不可重複讀和幻像讀。
3. ISOLATION_READ_COMMITTED: 保證一個事務修改的資料提交後才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的資料
4. ISOLATION_REPEATABLE_READ: 這種事務隔離級別可以防止髒讀,不可重複讀。但是可能出現幻像讀。
它除了保證一個事務不能讀取另一個事務未提交的資料外,還保證了避免下面的情況產生(不可重複讀)。
5. ISOLATION_SERIALIZABLE 這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。
除了防止髒讀,不可重複讀外,還避免了幻像讀。
Spring事務的只讀
“只讀事務”並不是一個強制選項,它只是一個“暗示”,提示資料庫驅動程式和資料庫系統,這個事務並不包含更改資料的操作,那麼JDBC驅動程式和資料庫就有可能根據這種情況對該事務進行一些特定的優化,比方說不安排相應的資料庫鎖,以減輕事務對資料庫的壓力,畢竟事務也是要消耗資料庫的資源的。“只讀事務”僅僅是一個性能優化的推薦配置而已,並非強制你要這樣做不可。
Spring事務的事務超時
為了使應用程式更好的執行,事務不能執行太長的時間。因此,宣告式事務的第四個特性就是超時。
Spring事務的回滾規則
預設情況下,事務只有在遇到執行期異常時才會回滾,而在遇到檢查型異常時不會回滾,但是也可以宣告事務在遇到特定的檢查型異常時像遇到執行期異常那樣回滾。同樣,你還可以宣告事務遇到特定的異常不回滾,即使這些異常是執行期異常。
原文釋出時間為:2018-10-30