spring AOP事务 @Transactional (声明式事务)

在这里插入图片描述

How to start, commit or rollback JDBC transactions
import java.sql.Connection;

Connection connection = dataSource.getConnection(); // (1)

try (connection) {
    connection.setAutoCommit(false); // (2)
    // execute some SQL statements...
    connection.commit(); // (3)

} catch (SQLException e) {
    connection.rollback(); // (4)
}
 @Transactional(propagation = Propagation.REQUIRED)

REQUIRED

SUPPORTS

MANDATORY

REQUIRES_NEW

NOT_SUPPORTED

NEVER

NESTED
  1. Required (default): My method needs a transaction, either open one for me or use an existing one → getConnection(). setAutocommit(false). commit().

  2. Supports: I don’t really care if a transaction is open or not, i can work either way → nothing to do with JDBC

  3. Mandatory: I’m not going to open up a transaction myself, but I’m going to cry if no one else opened one up → nothing to do with JDBC

  4. Require_new: I want my completely own transaction → getConnection(). setAutocommit(false). commit().

  5. Not_Supported: I really don’t like transactions, I will even try and suspend a current, running transaction → nothing to do with JDBC

  6. Never: I’m going to cry if someone else started up a transaction → nothing to do with JDBC

  7. Nested: It sounds so complicated, but we are just talking savepoints! → connection.setSavepoint()


  1. PROPAGATION_REQUIRED – 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
  2. PROPAGATION_SUPPORTS – 支持当前事务,如果当前没有事务,就以非事务方式执行。
  3. PROPAGATION_MANDATORY – 支持当前事务,如果当前没有事务,就抛出异常。
  4. PROPAGATION_REQUIRES_NEW – 新建事务,如果当前存在事务,把当前事务挂起。
  5. PROPAGATION_NOT_SUPPORTED – 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  6. PROPAGATION_NEVER – 以非事务方式执行,如果当前存在事务,则抛出异常。
  7. PROPAGATION_NESTED – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

举例浅析Spring嵌套事务
ServiceA#methodA(我们称之为外部事务),ServiceB#methodB(我们称之为外部事务)

ServiceA {
       
     void methodA() {
         ServiceB.methodB();
     }
  
}
  
ServiceB {
       
     void methodB() {
     }
       
}

PROPAGATION_REQUIRED
假如当前正要执行的事务不在另外一个事务里,那么就起一个新的事务 
比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候
  
  1、如果ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,
  ServiceB.methodB看到自己已经运行在ServiceA.methodA的事务内部,就不再起新的事务。
  这时只有外部事务并且他们是共用的,所以这时ServiceA.methodA或者
  ServiceB.methodB无论哪个发生异常methodA和methodB作为一个整体都将一起回滚。
  
  2、如果ServiceA.methodA没有事务,ServiceB.methodB就会为自己分配一个事务。
  这样,在ServiceA.methodA中是没有事务控制的。只是在ServiceB.methodB内的任何地方出现异常,
  ServiceB.methodB将会被回滚,不会引起ServiceA.methodA的回滚

PROPAGATION_SUPPORTS
如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行 

PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常

PROPAGATION_REQUIRES_NEW
启动一个新的, 不依赖于环境的 "内部" 事务.
这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行. 
 
 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,
 ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,
 那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,
 ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,他才继续执行。
 他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。
 因为ServiceB.methodB是新起一个事务,那么就是存在两个不同的事务。
 
1、如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。
2、如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try..catch捕获并处理,
(完全看methodB方法中catch后的逻辑了)ServiceA.methodA事务仍然可能提交;
如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。

使用场景:
不管业务逻辑的service是否有异常,Log Service都应该能够记录成功,所以Log Service的传播属性可以配为此属性。最下面将会贴出配置代码。

PROPAGATION_NOT_SUPPORTED
当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。

PROPAGATION_NEVER
不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,那么ServiceB.methodB就要抛出异常了。

PROPAGATION_NESTED
开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 嵌套事务开始执行时,  
它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 
嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交. 

比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,
ServiceB.methodB的事务级别为PROPAGATION_NESTED,那么当执行到ServiceB.methodB的时候,
ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的子事务并设置savepoint,
等待ServiceB.methodB的事务完成以后,他才继续执行。。
因为ServiceB.methodB是外部事务的子事务,那么

1、如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB也将回滚。
2、如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try..catch捕获并处理,
(MethodA canth后的处理逻辑)ServiceA.methodA事务仍然可能提交;
如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。

理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是:

PROPAGATION_REQUIRES_NEW 完全是一个新的事务,它与外部事务相互独立; 

而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 嵌套事务也会被 commit, 
这个规则同样适用于 roll back. 

原文链接:https://blog.csdn.net/yuanlaishini2010/article/details/45792069
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值