征服Spring事务Java学习笔记

spring事务

2017-01-23  本文已影响58人  小鱼嘻嘻

springmvc事务的配置方式

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

<!-- 第一种配置事务的方式 ,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>

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

<!-- 第二种配置事务的方式 ,代理-->
<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>

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

<!-- 第三种配置事务的方式,拦截器 (不常用)-->
<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>

这个就更少用了

 <!--数据库事务注解支持-->
    <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("......");
    }
    TransactionTemplate tt = new TransactionTemplate(); // 新建一个TransactionTemplate
    Object result = tt.execute(
        new TransactionCallback(){  
            public Object doTransaction(TransactionStatus status){  
                updateOperation();  
                return resultOfUpdateOperation();  
            }  
    }); // 执行execute方法进行事务管理

springmvc事务的传播行为

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

 //首先设置为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);
    }

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

流程图
    //首先设置为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没有数据。

流程图

第一种情况:
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 的最大区别了。

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

上一篇 下一篇

猜你喜欢

热点阅读