Spring 事務之聲明式事務

一.聲明式事務實現
  • 將編程式事務章節中applicationContext.xml修改下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <!-- 加載jdbc.property -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
              <list>
                <value>classpath:jdbc.properties</value> 
              </list>
        </property>
    </bean>
    <!-- 數據源配置, 使用DBCP數據庫連接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <!-- Connection Info -->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!-- Connection Pooling Info -->
        <property name="maxActive" value="3"/>
        <property name="defaultAutoCommit" value="false"/>
        <!-- 連接Idle一個小時后超時 -->
        <property name="timeBetweenEvictionRunsMillis" value="3600000"/>
        <property name="minEvictableIdleTimeMillis" value="3600000"/>
    </bean>
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">    
        <property name="dataSource" ref="dataSource"/>  
    </bean> 
    
    <bean id="abstractDao" abstract="true">
        <property name="dataSource" ref="dataSource"/>  
    </bean>
    
    <bean id="userDao" class="transaction.dao.UserDaoImp" parent="abstractDao"/>  
    <bean id="addressDao" class="transaction.dao.AddressDaoImp" parent="abstractDao"/>
    
    <bean id="userService" class="transaction.service.UserServiceImp">
        <property name="addressService" ref="addressService"/>
        <property name="userDao" ref="userDao"/>
    </bean>  
    
    <bean id="addressService" class="transaction.service.AddressServiceImp">
        <property name="addressDao" ref="addressDao"/>
    </bean>
    
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
            <tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED" read-only="true"/>
        </tx:attributes>
    </tx:advice>
    
    <aop:config>
        <aop:pointcut expression="execution(* transaction.service.*Imp.*(..))" id="serviceMethod" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
    </aop:config> 
</beans>

聲明式事務通過AOP代理方式實現事務管理,利用環繞通知TransactionInterceptor實現事務的開啟及關閉,而TransactionProxyFactoryBean內部也是通過該環繞通知實現的,因此可以認為是<tx:tags/>幫你定義了TransactionProxyFactoryBean,從而簡化事務管理

二.<tx:advice/>配置
<tx:advice id="……" transaction-manager="……">  
<tx:attributes>  
        <tx:method name="……"  
                           propagation=" REQUIRED"  
                           isolation="READ_COMMITTED"  
                           timeout="-1"  
                           read-only="false"  
                           no-rollback-for=""   
                           rollback-for=""/>  
        ……  
    </tx:attributes>  
</tx:advice> 
  • <tx:advice>:id用于指定此通知的名字, transaction-manager用于指定事務管理器,默認的事務管理器名字為“transactionManager”;
  • <tx:method>:用于定義事務屬性即相關聯的方法名;
    name:定義與事務屬性相關聯的方法名,將對匹配的方法應用定義的事務屬性,可以使用“”通配符來匹配一組或所有方法,如save將匹配以save開頭的方法,而“”將匹配所有方法;
    propagation:事務傳播行為定義,默認為“REQUIRED”,表示Required,其值可以通過TransactionDefinition的靜態傳播行為變量的“PROPAGATION_”后邊部分指定,如“TransactionDefinition.PROPAGATION_REQUIRED”可以使用“REQUIRED”指定;
    isolation: 事務隔離級別定義;默認為“DEFAULT”,其值可以通過TransactionDefinition的靜態隔離級別變量的“ISOLATION_”后邊部分指定,如“TransactionDefinition. ISOLATION_DEFAULT”可以使用“DEFAULT”指定:
    timeout:事務超時時間設置,單位為秒,默認-1,表示事務超時將依賴于底層事務系統;
    read-only:事務只讀設置,默認為false,表示不是只讀;
    rollback-for:需要觸發回滾的異常定義,以“,”分割,默認任何RuntimeException 將導致事務回滾,而任何Checked Exception 將不導致事務回滾;異常名字定義和TransactionProxyFactoryBean中含義一樣
    no-rollback-for:不被觸發進行回滾的 Exception(s);以“,”分割;異常名字定義和TransactionProxyFactoryBean中含義一樣;
三.多事務語義配置
  • 明式事務配置的最佳實踐
<tx:advice id="txAdvice" transaction-manager="transactionManager">  
<tx:attributes>  
           <tx:method name="save*" propagation="REQUIRED" />  
           <tx:method name="add*" propagation="REQUIRED" />  
           <tx:method name="create*" propagation="REQUIRED" />  
           <tx:method name="insert*" propagation="REQUIRED" />  
           <tx:method name="update*" propagation="REQUIRED" />  
           <tx:method name="merge*" propagation="REQUIRED" />  
           <tx:method name="del*" propagation="REQUIRED" />  
           <tx:method name="remove*" propagation="REQUIRED" />  
           <tx:method name="put*" propagation="REQUIRED" />  
           <tx:method name="get*" propagation="SUPPORTS" read-only="true" />  
           <tx:method name="count*" propagation="SUPPORTS" read-only="true" />  
          <tx:method name="find*" propagation="SUPPORTS" read-only="true" />  
          <tx:method name="list*" propagation="SUPPORTS" read-only="true" />  
          <tx:method name="*" propagation="SUPPORTS" read-only="true" />  
       </tx:attributes>  
</tx:advice>  
<aop:config>
        <aop:pointcut expression="execution(* transaction.service.*Imp.*(..))" id="serviceMethod" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
</aop:config> 
四.@Transactional實現事務管理
  • @Transactional配置
 @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED)
    public void save(final User user){
        userDao.save(user);  
        user.getAddress().setUserId(user.getId());  
        addressService.save(user.getAddress());
        throw new RuntimeException();
    }

    @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED,readOnly=true)
    public int countAll() {
        return userDao.countAll();
    }
  • 開啟@Transactional注解支持
<tx:annotation-driven proxy-target-class="false" transaction-manager="transactionManager" order="1"/>
  • Spring提供的<tx:annotation-driven/>用于開啟對注解事務管理的支持,從而能識別Bean類上的@Transactional注解元數據,其具有以下屬性:
    transaction-manager: 指定事務管理器名字,默認為transactionManager,當使用其他名字時需要明確指定;
    proxy-target-class: 表示將使用的代碼機制,默認false表示使用JDK代理,如果為true將使用CGLIB代理
    order: 定義事務通知順序,默認Ordered.LOWEST_PRECEDENCE,表示將順序決定權交給AOP來處理。

  • Spring使用@Transaction來指定事務屬性,可以在接口、類或方法上指定,如果類和方法上都指定了@Transaction,則方法上的事務屬性被優先使用,具體屬性如下:
    value: 指定事務管理器名字,默認使用<tx:annotation-driven/>指定的事務管理器,用于支持多事務管理器環境;
    propagation:指定事務傳播行為,默認為Required,使用Propagation.REQUIRED指定;
    isolation:指定事務隔離級別,默認為“DEFAULT”,使用Isolation.DEFAULT指定;
    readOnly:指定事務是否只讀,默認false表示事務非只讀;
    timeout:指定事務超時時間,以秒為單位,默認-1表示事務超時將依賴于底層事務系統;
    rollbackFor:指定一組異常類,遇到該類異常將回滾事務;
    rollbackForClassname:指定一組異常類名字,其含義與<tx:method>中的rollback-for屬性語義完全一樣;
    noRollbackFor:指定一組異常類,即使遇到該類異常也將提交事務,即不回滾事務;
    noRollbackForClassname:指定一組異常類名字,其含義與<tx:method>中的no-rollback-for屬性語義完全一樣;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 5.Spring的事務 通常情況下,J2EE有2種事務管理方式:全局事務和本地事務,2種事務都比較明顯的缺陷。 全...
    FTOLsXD閱讀 1,537評論 0 8
  • 這部分的參考文檔涉及數據訪問和數據訪問層和業務或服務層之間的交互。 Spring的綜合事務管理支持覆蓋很多細節,然...
    竹天亮閱讀 1,053評論 0 0
  • 1.IOC與DI inverse of control 控制反轉我們創建對象的方式反轉了。以前對象的創建由開發人員...
    蕊er閱讀 331評論 0 0
  • Spring 復習 [toc] spring介紹 三層架構中spring位置,連接三層。 spring一站式框架正...
    inke閱讀 779評論 0 11
  • 一> 程序中事務控制 環境準備 : 用戶訪問—》Action --》 Service---》Dao 一個業務的成...
    奮斗的老王閱讀 1,154評論 0 51