Spring事务及事务失效
一、背景
事务:原子性、一致性、隔离性、持久性
二、方式
1. 编程式事务:使用代码实现
Public interface PlatformTransactionManager{ // 由TransactionDefinition得到TransactionStatus对象 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; // 提交 Void commit(TransactionStatus status) throws TransactionException; // 回滚 Void rollback(TransactionStatus status) throws TransactionException; }
2. 声明式事务
a. 配置文件xml声明
b. @Transactional注解,加在类(Service)或者方法上,加在类上表示为此类的所有方法都应用相同配置的事务
三、@Transactional注解基本原理
1. 通过代理实现目标类,事务在代理类里进行增强
2. 由于代理类继承了目标类,所以只能对public的方法起作用
3. 必须在代理类外部调用,事务才能起作用;例如目标类里有两个方法,不加事务的方法调用另一个加了事务的方法,此时事务是不起作用的
四、事务失效场景
1.数据库引擎:MyIsam不支持事务,innoDB支持事务
2.方法不是public的
3.默认支持RuntimeException异常,而不支持其他异常
如果加上:@Transactional(rollbackFor = {Exception.class}),可支持所有异常
4.Exception被catch住
5.内部调用:同一个类中,不加事务的方法,调用加了事务的方法,则加了事务的方法事务失效
原因:spring事务回滚是通过动态代理处理的,但同一个类中,一个方法调用另一个方法,是通过this.xxx()调用的,不经过代理
解决方案:
a. 外层方法加事务,内层不用加
b. this调用改成动态代理调用(AopContext.currentProxy()
)
参考:
https://www.jianshu.com/p/5687e2a38fbc
https://mp.weixin.qq.com/s/JcHt99SAbNIlY063rmylpA