美文网首页
Spring 事务之声明式事务

Spring 事务之声明式事务

作者: zlb | 来源:发表于2016-11-26 16:50 被阅读249次
    一.声明式事务实现
    • 将编程式事务章节中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属性语义完全一样;

    相关文章

      网友评论

          本文标题:Spring 事务之声明式事务

          本文链接:https://www.haomeiwen.com/subject/zhkgpttx.html