spring事务

作者: 小鱼嘻嘻 | 来源:发表于2017-01-23 14:17 被阅读58次

    springmvc事务的配置方式

    springmvc配置事务方式有五种,好多都不怎么常用,说白了就是我也不会,最常用的基于注解的我还是有一些了解。我们来一起学习一下springmvc的事务配置方式。
    首先来看声明式事务

    • 1 使用tx标签
    <!-- 第一种配置事务的方式 ,tx-->
    <tx:advice id="txadvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />
            <tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception" />
            <tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="*" propagation="REQUIRED" read-only="true"/>
        </tx:attributes>
    </tx:advice>
    
    <aop:config>
        <aop:pointcut id="daoMethod" expression="execution(* com.dao.*.*(..))"/>
        <aop:advisor pointcut-ref="daoMethod" advice-ref="txadvice"/>
    </aop:config>
    

    这种主要是要求开发者在方法起名的时候需要保持前缀一直。

    • 2 使用代理的方式
    <!-- 第二种配置事务的方式 ,代理-->
    <bean id="transactionProxy"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"    abstract="true">
        <property name="transactionManager" ref="transactionManager"></property>
        <property name="transactionAttributes">
            <props>
                <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>
                <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>
                <prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>
                <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
            </props>
        </property>
    </bean>
    <bean id="userDao" parent="transactionProxy">
        <property name="target">
            <!-- 用bean代替ref的方式-->
            <bean class="com.dao.UserDaoImpl">
                <property name="sessionFactory" ref="sessionFactory"></property>
            </bean>
        </property>
    </bean>
    

    感觉和第一种很像,只是实现的方式不一样而已

    • 3 使用拦截器
    <!-- 第三种配置事务的方式,拦截器 (不常用)-->
    <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <property name="transactionManager" ref="transactionManager"></property>
        <property name="transactionAttributes">
            <props>
                <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>
                <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>
                <prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>
                <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
            </props>
        </property>
    </bean>
    <bean id="proxyFactory" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="interceptorNames">
            <list>
                <value>transactionInterceptor</value>
            </list>
        </property>
        <property name="beanNames">
            <list>
                <value>*Dao</value>
            </list>
        </property>
    </bean>
    

    这个就更少用了

    • 4 使用全注解
      这个就使用的很多了,我也就会使用这一种。因为这个使用很简单。直接看配置和代码
     <!--数据库事务注解支持-->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <tx:annotation-driven transaction-manager="txManager"/>
    

    再看一下代码:

        //首先设置为requried
        @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
        public void insert() {
            User user = new User();
            user.setName("yuxi");
           int pk =  userDao.insert(user);
            //新增账单
            orderService.insert(pk);
            System.out.println("......");
        }
    
    • 5 编程式
      意思就是自己在代码里实现事务,这个还是一个比较好的方式,可以精确的控制边界。
        TransactionTemplate tt = new TransactionTemplate(); // 新建一个TransactionTemplate
        Object result = tt.execute(
            new TransactionCallback(){  
                public Object doTransaction(TransactionStatus status){  
                    updateOperation();  
                    return resultOfUpdateOperation();  
                }  
        }); // 执行execute方法进行事务管理
    

    springmvc事务的传播行为

    事务的传播行为有七种,接下来我们就一种一种探讨一下。

      1. propagation_required 默认的
        具体来说就,如果当前没有事务就会新建一个事务,如果有事务就会加入当前事务。
     //首先设置为requried
        @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
        public void insert() {
            User user = new User();
            user.setName("yuxi");
           int pk =  userDao.insert(user);
            //新增账单
           //因为有事务所有,orderService.insert(pk)会加入当前事务
            orderService.insert(pk);
        }
    

    总结起来就是这两个方法要么一起执行,要么一起回滚,不会一个执行成功,另外一个执行回滚。

    流程图
    • 2 propagation_requried_new
      具体来说就是,methodA设置为requried,methodB设置为requried_new,当执行methodB的时候,会先挂起methodA,等待methodB执行完了,methodA才继续执行。
      requried和requried_new 区别
      主要在于回滚程度了,methodB是新启的一个事务。
      如果methodB执行失败,methodB肯定回滚,如果methodA捕获这个异常,methodA可以正常提交,如果methodA没有捕获methodA也回滚。
      如果methodB执行成功,methodA执行失败,那么methodB不会回滚,methodA会执行回滚。
        //首先设置为requried
        @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
        public void insert() {
            User user = new User();
            user.setName("yuxi");
           int pk =  userDao.insert(user);
            //requried_new ,如果执行失败
            try {
                orderService.insert(pk);
            }catch (Exception e){
                //不做处理,让当前事务执行完
            }
            System.out.println("......");
        }
    
      //requried_new
        @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
        public  void insert(int userId) {
            Order order = new Order();
            order.setDescs("desc yx");
            order.setOrderId("0101");
            order.setUserId(userId);
            orderDao.insert(order);
            int i = 1/0;
        }
    

    执行结果:
    user表有数据,order表没有数据。
    我们在换成另外一种情况, orderService.insert(pk);执行成功

     //首先设置为requried
        @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
        public void insert() {
            User user = new User();
            user.setName("yuxi");
           int pk =  userDao.insert(user);
            //requried_new ,如果执行失败
    //        try {
                orderService.insert(pk);
    //        }catch (Exception e){
    //            //不做处理,让当前事务执行完
    //        }
            int i = 1/0;
            System.out.println("......");
        }
    
    
     //requried_new
        @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
        public  void insert(int userId) {
            Order order = new Order();
            order.setDescs("desc yx");
            order.setOrderId("0101");
            order.setUserId(userId);
            orderDao.insert(order);
    //        int i = 1/0;
        }
    

    执行结果:
    order表有数据,user没有数据。

    流程图
    • 3 propagation_nested
      具体来说,就是嵌套事务。

    第一种情况:
    nested事务抛了异常,外部事务捕获了异常。

     //首先设置为requried
        @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
        public void insert() {
            User user = new User();
            user.setName("yuxi");
           int pk =  userDao.insert(user);
            //NESTED ,如果执行失败
            try {
                orderService.insert(pk);
            }catch (Exception e){
                System.out.println("可以继续执行这里面的逻辑.....");
            }
            System.out.println("当前事务继续执行......");
        }
     //NESTED
        @Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
        public  void insert(int userId) {
            Order order = new Order();
            order.setDescs("desc yx");
            order.setOrderId("0101");
            order.setUserId(userId);
            orderDao.insert(order);
            int i = 1/0;
        }
    

    结果是:
    外部事务正常执行,嵌套事务回滚。
    第二种情况:嵌套事务正常执行完成,外部事务抛了异常。

       //首先设置为requried
        @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
        public void insert() {
            User user = new User();
            user.setName("yuxi");
           int pk =  userDao.insert(user);
            //NESTED ,如果执行失败
            try {
                orderService.insert(pk);
            }catch (Exception e){
                System.out.println("可以继续执行这里面的逻辑.....");
            }
            int i = 1/0;
            System.out.println("当前事务继续执行......");
        }
     //NESTED
        @Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)
        public  void insert(int userId) {
            Order order = new Order();
            order.setDescs("desc yx");
            order.setOrderId("0101");
            order.setUserId(userId);
            orderDao.insert(order);
    //        int i = 1/0;
        }
    

    结果是:
    两个都被回滚了,我理解这个就是嵌套事务和requried_new 的最大区别了。

    • 4 propagation_supported
      具体来说,就是支持当前事务,如果没有就以非事务的方式运行。

    • 5 propagation_not_supported
      具体来说就是不支持以事务的方式运行,如果当前有事物就会挂起。

    • 6 propagation_never
      具体来说,就是不支持事务的方式运行,如果有事务就会抛出异常。

    • 7 propagation_mandatory
      具体来说,就是支持当前事务,如果当前没有事务,就抛出异常。
      后面的基本都不常用。

    参考文章:
    http://blog.csdn.net/it_wangxiangpan/article/details/24180085
    http://blog.csdn.net/paincupid/article/details/48185597

    相关文章

      网友评论

        本文标题:spring事务

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