Spring中的事務管理

1.   事務概述

事務(Transaction)是訪問並可能更新數據庫中數據的程序執行單元,通常事務開始(begin transaction)和事務結束(end transaction)之間執行的全體操作組成。例如我們平時的轉賬操作,從開始執行轉賬,到收款用戶確認收款,最終金額增加,這就是一個事務。

爲什麼我們要加入事務管理?藉助以上的轉賬實例來進行說明,假設A向B賬戶轉賬100元,那麼最基本的兩個操作就是A賬戶的金額減少100元,然後B賬戶的金額增加100元,存在一定的先後順序。倘若在A完成轉賬之後,A的金額減少了100元,但是信息傳輸途中發生了某些異常,導致B沒有接受到轉賬信息,那麼B的金額沒有增加。最終的結果是A的金額減少了100元,而B的維持不變。這樣的場景不符合我們日常生活的實際,因此我們引入事務管理,一旦在事務發生中斷,事務立即回滾到開始之前的狀態,也就是A減少的那100元金額會退還到A的賬戶。

事務作爲一個不可分割的邏輯工作單元,一般具備ACID四大特性:

1)  原子性(一個事務中的多個操作要麼都成功要麼都失敗)

2)  一致性(一個事務必須讓數據庫從一個一致性狀態到另一個一致性狀態,簡單地舉例就是轉賬前後兩個人的總金額應該不變)

3)  隔離性(事務與事務之間應該互不干擾)

4)  持久性(事務一旦提交,它對數據庫的改變是永久性的)

2.   Spring事務管理

Spring爲我們提供了兩種事務管理方式。一種是通過編碼實現的編程式事務,另一種是基於Spring AOP的聲明式事務。聲明式事務管理通過切面實現將具體業務邏輯與事務處理解耦,使業務代碼邏輯不受污染, 因此在實際使用中聲明式事務用的比較多。

Spring中聲明式事務處理有兩種方式,一種是在配置文件(xml)中做相關的事務規則聲明,另一種是基於@Transactional 註解的方式。

2.1註解模式的事務管理

         首先,我們在spring容器中配置一個事物管理的bean對象,DataSourceTransactionManager對象,這裏也有兩種方式,一種是在配置類中配置(全註解模式),另一種是在spring配置文件中配置(半註解模式)。

配置類中配置事物管理類,首先要開啓spring註解驅動的事務管理,可以通過在類名上方添加@ EnableTransactionManagement註解的方式實現,然後在這個類中配置事務管理對象,這裏的DataSource要與數據庫連接的數據源保持一致:

@Bean("transactionManager")
public DataSourceTransactionManager getDataSourceTransactionManager(
		DataSource ds){
	DataSourceTransactionManager transactionManager=
			new DataSourceTransactionManager();
	transactionManager.setDataSource(ds);
	return transactionManager;
}

        Xml配置文件中配置管理類並開啓事物管理模式:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
</bean>
<!--設置註解驅動的事務管理  -->
<tx:annotation-driven transaction-manager="transactionManager"/>  

       配置好事務管理註解以後,就可以在類或者方法上使用@Transactional進行事務管理。當把@Transactional註解加在類上時,表示類中的所有public修飾的方法全都配置相同的事物管理信息。當@Transactional修飾方法時,表示方法對方法進行事物管理。這裏需要注意兩點:一是@Transactional只能用來修飾public權限的方法,其餘的不起作用;二是如果類和類裏的方法都是用了@Transactional註解,方法上的事無屬性優先級別較高,會覆蓋類上的相關設置。

         @Transactional註解後表示啓動spring默認的事務管理模式,也可以添加一些屬性來對方法採取不同的事務管理模式,下面總結了一些常用的屬性:

Value:當在配置文件中有多個 TransactionManager , 可以用該屬性指定選擇哪個事務管理器。

Propagation:事務的傳播行爲,默認值爲 REQUIRED。

Isolation:事務的隔離度,默認值採用 DEFAULT。

Timeout:事務的超時時間,默認值爲-1。如果超過該時間限制但事務還沒有完成,則自動回滾事務。

read-only :指定事務是否爲只讀事務,默認值爲 false;爲了忽略那些不需要事務的方法,比如讀取數據,可以設置read-only 爲 true。

rollback-for:用於指定能夠觸發事務回滾的異常類型,如果有多個異常類型需要指定,各類型之間可以通過逗號分隔。

no-rollback- for:拋出 no-rollback-for 指定的異常類型,不回滾事務。

2.2spring配置文件中的事務管理

         配置文件中配置事物管理可以分爲三步。

1)在spring配置文件中配置事務管理器:

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

2)定義事物策略,這裏是對所有的public方法進行相關事務管理設置:

<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="save*" propagation="REQUIRED"/>
		<tx:method name="delete*" propagation="REQUIRED"/>
		<tx:method name="update*" propagation="REQUIRED"/>
		<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
		<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
	</tx:attributes>
</tx:advice>

也可以針對某一方法進行特殊設置:

<tx:advice id="txAdvice"  transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*"
        propagation="REQUIRED"
        isolation="READ_COMMITTED"
        timeout="-1"
        read-only="false"
        rollback-for="java.lang.Throwable"
        no-rollback-for=”NoTransactionException”/>
    </tx:attributes>
</tx:advice>

3)配置事物切面,這裏設置的一種細粒度的事物管理,對service中的所有方法進行管理,還有一種粗粒度的事務管理,expression=”within("com.jt.manage.service..*")管理的是service包中的所有類。

<aop:config>
	<aop:pointcut expression="execution(* com.jt.manage.service..*.*(..))" id=pointCut"/>
	<aop:advisor advice-ref="txAdvice" ref="pointCut"/>
</aop:config>
3.spring事物拓展
3.1spring事物傳播特性

         事務傳播特性(propagation):事務方法之間相互調用時,事務的傳播方式。

@Transactional(propagation=Propagation.REQUIRED) 如果沒有事務創建新事務, 如果當前有事務參與當前事務,這是事物管理的默認方式,也是需要重點掌握的。

@Transactional(propagation=Propagation.SUPPORTS)支持事務, 如果沒有事務也不會創建新事務,也是比較常用的,一般用在查詢方法中。

@Transactional(propagation=Propagation.REQUIRES_NEW)必須是新事務, 如果有當前事務, 掛起當前事務並且開啓新事務。

@Transactional(propagation=Propagation.MANDATORY)必須有事務, 如果當前沒有事務就拋異常。

@Transactional(propagation=Propagation.NEVER)絕對不能有事務, 如果在事務中調用則拋出異常。

@Transactional(propagation=Propagation.NESTED)必須被嵌套到其他事務中。

@Transactional(propagation=Propagation.NOT_SUPPORTED)不支持事務。

3.2事物隔離級別

         總所周知,併發訪問時程序需要解決的一個重要問題,當多個事物併發執行時,可能會引發髒讀、不可重複讀和幻讀等問題。髒讀是一個事務中讀取到另一個事務沒有提交的數據。不可重複讀是在一個事務中兩次查詢的結果不一樣(針對update操作)。幻讀是在一個事務中兩次查詢的結果不一樣(針對insert操作)。

當多個事務併發執行時,可通過設置事務的隔離級別保證事務的完整性,一致性。

事務的隔離級別從低到高有如下幾種方式:

1)READ_UNCOMMITTED (此級別可能會出現髒讀)

2)READ_COMMITTED(此級別可能會出現不可重複讀)

3)REPEATABLE_READ(此級別可能會出現幻讀)

4)SERIALIZABLE(多事務串行執行)

         spring中一般採用@Transactional(isolation=Isolation.READ_COMMITTED) 方式聲明級別, 這種方式是併發性能和安全性折中的選擇,是大多數軟件項目採用的隔離級別。



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