在spring的事務管理高層抽象層中主要包含3個借口:TransactionDefinition,PlatformTransactionManager,TransactionStatus
TransactionDefinition用於描述隔離級別、超時時間、是否為只讀事務和事務傳播規則
TransactionStatus代表一個事務的具體運行狀態、以及保存點
PlatformTransactionManager一個高層次的接口,包含3個方法commit、rollback和getTramsaction
事務傳播級別:
PROPAGATION_REQUIRED--支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。適用於save、update、delete等操作
PROPAGATION_SUPPORTS--支持當前事務,如果當前沒有事務,就以非事務方式執行。一般讀db的操作可是使用此方式,同時將事物設置為ReadOnly。
PROPAGATION_MANDATORY--支持當前事務,如果當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW--新建事務,如果當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED--以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。適用於優先級別很高的方法。
PROPAGATION_NEVER--以非事務方式執行,如果當前存在事務,則拋出異常。
PROPAGATION_NESTED--如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則進行與PROPAGATION_REQUIRED類似的操作。
三種事務管理方式:編程式事務管理、使用xml配置聲明式事務、使用注解配置聲明式事務
1.編程式事務管理
略
2.使用xml配置聲明式事務
事務屬性信息配置規則
<!-- 傳播行為,隔離級別(可選),是否為只讀(可選),發生這些異常時回滾(可選),發生這些異常時照樣提交(可選)--> <prop>PROPAGATION,ISOLATION,readOnly,_Exception,+Exception</prop>
第一種:也是我們最常用的方法了,它適用於你的庫表比較少的情況下。
<bean id="fundServiceDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!-- 配置事務管理器 --> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 此屬性指定目標類本省是否是代理的對象,如果目標類沒有實現任何類,就設為true代表自己 --> <property name="proxyTargetClass"> <value>false</value> </property> <!-- 目標實現的接口 --> <property name="proxyInterfaces"> <value>com.jack.fund.service.IFundService</value> </property> <!-- 目標bean --> <property name="target"> <ref bean="fundService" /> </property> <!-- 配置事務屬性 --> <property name="transactionAttributes"> <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
以下可能還有其他的xxxServiceDAOProxy.大家可以看出針對每一個功能模塊配置一個業務代理服務。如果模塊多大話,就顯得代碼有點多了,發現他們只是稍微一點不一樣。這時我們就應該想到繼承的思想。用第二種方法。
第二種:配置聲明式事務的方法如下。這種情況適合相對比較多的模塊時使用。
<!-- 利用繼承的思想簡化配置,要把abstract="true" --> <bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true"> <!-- 配置事務管理器 --> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 配置事務屬性 --> <property name="transactionAttributes"> <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
而具體的模塊可以簡單的這樣配置。只要指明它的parent(父類)就可以了。父類一般把abstract="true",因為在容器加載的時候不需要初始化,等到用的時候再有它的子類調用的時候,再去初始化。
<bean id="fundServiceDAOProxy" parent="transactionBase" > <property name="target"> <ref bean="fundService" /> </property> </bean>
這樣配置的話,如果有多個像fundService這樣模塊時,可以少些很多重復的代碼。
第三種:配置聲明式事務的方法如下。主要利用BeanNameAutoProxyCreator自動創建事務代理
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 配置事務屬性 --> <property name="transactionAttributes"> <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>fundService</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean>
這種方法主要利用了攔截器的原理。
前三種方法一般都必需指定具體的模塊bean.如果模塊過多話,比如一個大型的網站一般有幾十個模塊。我們就得考慮用第四種的配置方式了。自動創建事務代理的方式了。
第四種:配置聲明式事務的方法如下。
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 自動代理 --> <bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <!-- 可以是Service或DAO層(最好是針對業務層*Service) --> <property name="beanNames"> <list> <value>*Service</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean>
自動代理還有一種用法就是結合正規表達式和advice使用。
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" /> <bean id="regexpMethodPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref bean="transactionInterceptor" /> </property> <property name="pattern"> <value>.*</value> </property> </bean>
這個方法可以針對具體的模塊進行攔截並進行事務處理。
在你的實際項目中,你可以根據你的情況選用不同的方法。
詳細:http://www.cnblogs.com/rushoooooo/archive/2011/08/28/2155960.html
3.使用注解配置聲明式事務 @Transaction
注解本身具有一些普遍使用的默認屬性,所以往往只加一個@Transaction就可以了
@Transaction注解屬性說明
value:可以綁定到不同的事務管理器上
propagation:事務傳播行為
isolation:事務隔離級別
readOnly:是否為只讀
timeout:超時時間
rollbackFor:一組異常類,遇到時進行回滾,類型為Class<? extemds Tjrpwab;e>[],默認為{}
rollbackForClassName:一組異常類,遇到時進行回滾,類型為String[],默認為{}
noRollbackFor:一組異常類,遇到時不回滾,類型為Class<? extemds Tjrpwab;e>[],默認為{}
noRollbackForClassName:一組異常類,遇到時不回滾,類型為String[],默認為{}