Spring基礎系列——事務Transaction


在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[],默認為{}

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM