补充spring事务传播性没有考虑的几种情况

9 篇文章 0 订阅

spring传播机制的讲解参考:
https://segmentfault.com/a/1190000013341344#articleHeader3
http://blog.51cto.com/jaeger/1761660
以下15种情况,大多都是网上讲解spring传播性不会讲的,以下都是新自测试过的结果,并写了几条总结。

spring事务的几种情况

需要注意的是,如果抛出的异常不是RuntimeException而是Exception,则需要通过rollbakfor指定,不然事务当中抛出的Exception异常是不回滚的。

1.同类中,事务方法a调用非事务方法b。在b的最后抛异常,a捕获b的异常。结果是:都不回滚。
2.同类中,事务方法a调用非事务方法b。在b的最后抛异常,a不捕获b的异常。结果是:都回滚。
3.同类中,事务方法a调用非事务方法b。在a的最后抛出异常。结果是:都回滚。

4.同类中,事务方法a调用配置过事务的方法b。在b的最后抛出异常,a捕获b的异常。结果是:都不回滚。
5.同类中,事务方法a调用配置过事务的方法b。在b的最后抛出异常,a不捕获b的异常。结果是:都回滚。
6.同类中,事务方法a调用配置过事务的方法b。在a的最后抛出异常,结果是:都回滚。

7.同类中,非事务方法a调用配置过事务的方法b,在b最后抛出异常,a捕获b的异常。结果是:都不回滚。
8.同类中,非事务方法a调用配置过事务的方法b,在b最后抛出异常,a不捕获b的异常。结果是:都不回滚。
9.同类中,非事务方法a调用配置过事务的方法b,在a最后抛出异常。结果是:都不回滚。

10.非同类中,事务方法a调用非事务方法b,在b的最后抛出异常,a捕获导常。结果是:都不回滚。
11.非同类中,事务方法a调用非事务方法b,在b的最后抛出异常,a不捕获异常。结果是:都回滚。
12.非同类中,事务方法a调用非事务方法b,在a的最后抛出异常。结果是:都回滚。

13.非同类中,事务方法a调用嵌套事务方法b,在b的最后抛出异常,a捕获b的异常。结果是:只有b回滚。
14.非同类中,事务方法a调用嵌套事务方法b,在b的最后抛出异常,a不捕获b的异常。结果是:都回滚。
15.非同类中,事务方法a调用嵌套事务方法b,在a的最后抛出异常。结果是:都回滚。

16.非同类中,非事务方法a调用事务方法b,在b的最后抛出异常,a捕获b的异常。结果是:只有b回滚。
17.非同类中,非事务方法a调用事务方法b,在b的最后抛出异常,a不捕获b的异常。结果是:只有b回滚。
18.非同类中,非事务方法a调用事务方法b,在a的最后抛出异常。结果是:都不回滚。

19.非同类中,非事务方法a调用嵌套事务方法b,在b的最后抛出异常,a捕获b的异常。结果是:只有b回滚。
20.非同类中,非事务方法a调用嵌套事务方法b,在b的最后抛出异常,a不捕获b的异常。结果是:只有b回滚。
21.非同类中,非事务方法a调用嵌套事务方法b,在a的最后抛出异常。结果是:都不回滚。

22.非同类中,事务方法a多级嵌套调用非事务方法,在任一级非事务方法中抛出异常,a捕获异常,结果是都不回滚。
23.非同类中,事务方法a多级嵌套调用非事务方法,在任一级非事务方法中抛出异常,a不捕获异常。结果是都回滚。
24.非同类中,事务方法a多级嵌套调用非事务方法,在a的最后抛出异常。结果是都回滚。

以下是对第18条的一个举例:

A类中,a为非事务方法

 public void a()  throws Exception {
      Task t = new Task();
      t.setOrderContent("非事务方法测试A");
      dao.insert(t);
      new B().b();
      throw new Exception();
  }

B类中,b为事务方法

 public void b()  {
      Task t = new Task();
      t.setOrderContent("事务方法测试B");
      dao.insert(t);
  }

以下是对第13条的一个举例:非同类中,事务方法a调用嵌套事务方法b,在b的最后抛出异常,a捕获b的异常。结果是:只有b回滚。

A类中,a为事务方法

 public void a()   {
     try{
          Task t = new Task();
          t.setOrderContent("非事务方法测试A");
          // 由于异常被捕获了,所以下面的插入不会回滚,因为异常被捕获后,方法a感知不到了
          dao.insert(t);
          new B().b();
      }catch(Exception e){
          e.printStack();
      }
  }

B类中,b为嵌套事务方法

 public void b() throws Exception {
      Task t = new Task();
      t.setOrderContent("事务方法测试B");
      dao.insert(t);
      throw new Exception();
  }

总结

  1. spring的事务传播属性不适用于同类中的方法调用,即事务方法在被同类中的方法调用时会被当作非事务方法。

  2. 事务方法调用非事务方法(包括本类中事务不生效的方法)时,事务方法捕获了被调用方法里的异常时就都不会回滚,不捕获就都回滚。

  3. 非事务方法调用非事务方法(包括本类中事务不生效的方法)和调用嵌套事务时一样都不会互不影响,即都会自动提交。

  4. 事务方法多级嵌套调用非事务方法,和调用一级非事务方法结果是一致的,即只要事务方法捕获了异常就都不回滚,不捕获就都回滚。

  5. 一个方法b加入到事务方法a中时,不论b抛出的异常是否被a捕获,结果是整个事务都会回滚。因为始终是一个事务。

  6. 事务方法a调用一个新开的事务方法b,在b的最后抛出异常,a捕获异常。结果是只有b回滚。因为都不在同一个事务当中了。

事务在spring中的几个重点:

  1. 事务的隔离级别是数据库本身的事务功能,然而事务的传播属性则是Spring自己为我们提供的功能,数据库事务没有事务的传播属性这一说法。

  2. 事务的前提是要数据库支持事务

  3. 事务传播机制只适用于不同bean之间的方法调用

  4. 只要一个方法开启了事务,那么就从此时设置了一个事务点。

  5. 一个线程的事务不会影响到另外一个线程的事务。例如,插入日志的方法是需要始终保持成功的,而不希望因为事务内的某些方法导致的回滚而回滚,所以一般的都会新开线程来执行插入日志的方法。

  6. 一个线程在没有结束当前事务的时候,是无法释放资源来执行其它事务的。

事务在数据库中的几个重点:

  1. 数据库执行事务的时候,是先将数据插入到日志中,如果没有遇到回滚,则在提交事务的时候将日志操作同步到数据库。如果回滚的话,则日志的操作不再插入数据库中。

  2. 如果发生回滚,则主键还是会增大的即主键会变得不连续。例如,本应该插入的数据id为100,但是发生了回滚,则后面再正确插入的数据的主键会是101。

  3. JDBC对事务的支持是放在Connection连接中的。

补充

如果使用的@Transactionl注解,最好不要加在接口上。
在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值