码迷,mamicode.com
首页 > 编程语言 > 详细

实例详解Spring的事务传播机制(二)

时间:2016-04-08 20:14:11      阅读:806      评论:0      收藏:0      [点我收藏+]

标签:spring   事务传播机制   

上面我们讨论了NEVER和MANDATORY的作用,下面我们接着讨论其他情况。

3. SUPPORTS

如果有事务则加入该事务,如果没有存在的事务则以非事务的方式运行。

我们先让insertSubTable方法在无事务的情况下运行。配置文件为:

<tx:attributes>  
    <!--
    <tx:method name="insertSuperTable" propagation="REQUIRED"/> 
    -->
    <tx:method name="insertSubTable" propagation="SUPPORTS"/> 
</tx:attributes>

父事务类:

@Component
public class TransactionSuper {
    @Autowired
    TransactionSub transactionSub;
    String insertSuperTable1 = "insert into super_table values (1, ‘super1‘)";
    String insertSuperTable2 = "insert into super_table values (2, ‘super2‘)";
    
    public void insertSuperTable(AbstractApplicationContext ctx) throws Exception{
    	System.out.println("========insertSuperTable start========");
    	JdbcTemplate jt = (JdbcTemplate)ctx.getBean("jdbcTemplate");
    	jt.execute(insertSuperTable1);
    	transactionSub.insertSubTable(ctx);
    	jt.execute(insertSuperTable2);
    	System.out.println("========insertSuperTable end========");
    }
}

子事务类:

@Component
public class TransactionSub {
    String insertSubTable1 = "insert into sub_table values (1, ‘sub1‘)";
    String insertSubTable2 = "insert into sub_table values (2, ‘sub2‘)";

    public void insertSubTable(AbstractApplicationContext ctx) throws Exception {
        System.out.println("========insertSubTable start========");
        JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
        jt.execute(insertSubTable1);
        jt.execute(insertSubTable2);
        System.out.println("========insertSubTable end========");
    }
}

运行测试方法:

技术分享

技术分享

技术分享

从上面可以看出,如果没有父事务,SUPPORTS标注的方法完全是非事务运行的。下面我们给它一个父事务,先修改配置文件:

<tx:attributes>  
    <tx:method name="insertSuperTable" propagation="REQUIRED"/> 
    <tx:method name="insertSubTable" propagation="SUPPORTS"/> 
</tx:attributes>

然后运行测试方法:

技术分享

技术分享

技术分享

从上面可以看出子方法加入了父方法的事务,所以父方法对数据库的修改是对子方法可见的。

我们来看看发生异常时的回滚,这里只讨论有事务存在的情况,因为如果没有事务,它就以非事务方式运行,也就不存在回滚。

①RuntimeException

MANDATORY一样,SUPPORTS标注的方法是直接加入父事务,成为父事务的一部分,他们共享一个connect。所以当子事务抛出RuntimeException回滚的时候,父事务也不得不一起回滚。

②Throwable和Exception

MANDATORY一样,如果不配置rollback-for属性,抛出Throwable和Exception都不会导致父子事务回滚,而是在哪儿出异常就在哪儿提交,就有可能出现部分提交的现象。

我们可以用rollback-for属性来让抛Throwable和Exception时也回滚。由于SUPPORTS标注的方法是直接加入父事务,所以子类发生Throwable或Exception,就会父子一起回滚。




4. NOT_SUPPORTED

当前方法不运行在任何事务之中,如果有已经存在的事务则将该事务挂起,直到当前方法以非事务的方式执行完毕,挂起的事务才会继续执行。我们修改下配置文件:

<tx:attributes>  
    <tx:method name="insertSuperTable" propagation="REQUIRED"/>
    <tx:method name="insertSubTable" propagation="NOT_SUPPORTED"/> 
</tx:attributes>

然后执行测试方法:

技术分享

技术分享

技术分享

从上面可以看出子方法以非事务方法执行,而父方法以事务方式执行,父方法对数据库的修改是否对子方法可见,取决于数据库的事务隔离级别。如果隔离级别是Read Uncommitted,则可见。

我再来看看异常回滚:

①RuntimeException

我们先让insertSubTable方法抛出一个RuntimeException:

子事务类:

@Component
public class TransactionSub {
    String insertSubTable1 = "insert into sub_table values (1, ‘sub1‘)";
    String insertSubTable2 = "insert into sub_table values (2, ‘sub2‘)";

    public void insertSubTable(AbstractApplicationContext ctx) throws Exception {
        System.out.println("========insertSubTable start========");
        JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
        jt.execute(insertSubTable1);
        ExceptionUtils.throwRuntimeException();  //这里抛出RuntimeException
        jt.execute(insertSubTable2);
        System.out.println("========insertSubTable end========");
    }
}

执行测试类:

技术分享

技术分享

技术分享

从上面可以看出,这里抛RuntimeException回滚的效果有点不一样,并不是所以操作都回滚。因为insertSuperTable方法由于在事务中,所以所有插入都回滚了。但insertSubTable不属于任何事务,所以第一个插入成功了,后来就抛异常退出了。

②Throwable和Exception

如果在无事务的insertSubTable中抛出异常,则在哪儿出异常就在哪儿提交。rollback-for属性对NOT_SUPPORTED无效,因为它本身就不在事务中,也不会回滚。



实例详解Spring的事务传播机制(一)

本文出自 “銅鑼衛門” 博客,请务必保留此出处http://jaeger.blog.51cto.com/11064196/1761851

实例详解Spring的事务传播机制(二)

标签:spring   事务传播机制   

原文地址:http://jaeger.blog.51cto.com/11064196/1761851

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!