@Transactional 同一个类中无事务方法a()内部调用有事务方法b()的问题
https://blog.csdn.net/u010235716/article/details/90171802
1. 事务的4种特性
序号 参数 含义
1 原子性(Atomicity) 事务是数据库的逻辑工作单位,它对数据库的修改要么全部执行,要么全部不执行。
2 一致性(Consistemcy) 事务前后,数据库的状态都满足所有的完整性约束。
3 隔离性(Isolation) 并发执行的事务是隔离的,一个不影响一个。通过设置数据库的隔离级别,可以达到不同的隔离效果
4 持久性(Durability) 在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
2.Transactional()控制事务传播的配置项目(默认Propagation.REQUIRED)
@Transactional(propagation=Propagation.REQUIRED) //控制事务传播。默认是Propagation.REQUIRED
@Transactional(isolation=Isolation.DEFAULT) //控制事务隔离级别。默认跟数据库的隔离级别相同
@Transactional(readOnly=false) //控制事务可读写、只可读。默认可读写
@Transactional(timeout=30) //控制事务的超时时间,单位秒。默认跟数据库的事务控制系统相同
@Transactional(rollbackFor=RuntimeException.class) //控制事务遇到哪些异常会回滚。默认是RuntimeException
@Transactional(rollbackForClassName=RuntimeException) //同上
@Transactional(noRollbackFor=NullPointerException.class) //控制事务遇到哪些异常不会回滚。默认遇到RuntimeException回滚
@Transactional(noRollbackForClassName=NullPointerException)//同上
3.事务的7中传播特性4. 事务的传播案例:
序号 传播行为 含义
1 REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
2 SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
3 MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
4 NESTED 如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行
5 NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常
6 REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个已经存在的事务挂起
7 NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务
4.举个上手的按例:事务在A类的a()方法中调用B类的b()方法的传播案例
A.a() B.b()的事务配置 a()没有事务的结果 a()有事务的结果
REQUIRED b()创建自己的事务; b()接受a()的事务
SUPPORTS b()不创建自己的事务; b()接受a()的事务
MANDATORY b()报异常 b()接受a()的事务
NESTED b()创建自己的事务; b()接受a()的事务,成为a()嵌套的子事务
NEVER b()不创建自己的事务; b()报异常
REQUIRES_NEW b()创建自己的事务; b()不接受a()的事务,b()先执行,内层事务失败不会影响外层事务
NOT_SUPPORTED b()不创建自己的事务; b()不接受a()的事务,b()先执行
spring 事务处理中,同一个类中:A方法(无事务)调B方法(有事务),事务不生效问题
详见:https://blog.csdn.net/liming19890713/article/details/79225894
https://blog.csdn.net/m0_38027656/article/details/84190949
https://blog.csdn.net/levae1024/article/details/82998386
研究源码、调试程序得出结论:
A如果没有受事务管理: 则线程内的connection 的 autoCommit为true。
B得到事务时事务传播特性依然生效,得到的还是A使用的connection,但是 不会改变autoCommit的属性。
所以B当中是按照每条sql进行提交的。
解决办法:
可以把方法B放到另外一个service或者dao,然后把这个server或者dao通过@Autowired注入到方法A的bean里面,这样即使方法A没用事务,方法B也可以执行自己的事务了。
Spring 事务机制回顾
Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务. 结果造成开发人员在设计 事务方法时束手束脚,生怕一不小心就踩到地雷。
其实这是不认识Spring事务传播机制而造成的误解,Spring对事务控制的支持统一在TransactionDefinition类中描述,该类有以下 几个重要的接口方法:
int getPropagationBehavior():事务的传播行为
int getIsolationLevel():事务的隔离级别
int getTimeout():事务的过期时间
boolean isReadOnly():事务的读写特性
除了事务的传播行为外,事务的其他特性Spring是借助底层资源的功能来完成的,Spring无非只充当个代理的角色。但是事务的传播行为却是Spring凭借自身的框架提供的功能 ;
Spring事务传播属性:
所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。Spring支持以下7种事务传播行为
Spring事务传播属性:
1.propagation-required: 支持当前事务,如果有就加入当前事务中;如果当前方法没有事务,就新建一个事务;
2.propagation-supports: 支持当前事务,如果有就加入当前事务中;如果当前方法没有事务,就以非事务的方式执行;
3.propagation-mandatory: 支持当前事务,如果有就加入当前事务中;如果当前没有事务,就抛出异常;
4.propagation-requires_new: 新建事务,如果当前存在事务,就把当前事务挂起;如果当前方法没有事务,就新建事务;
5.propagation-not-supported: 以非事务方式执行,如果当前方法存在事务就挂起当前事务;如果当前方法不存在事务,就以非事务方式执行;
6.propagation-never: 以非事务方式执行,如果当前方法存在事务就抛出异常;如果当前方法不存在事务,就以非事务方式执行;
7.propagation-nested: 如果当前方法有事务,则在嵌套事务内执行;如果当前方法没有事务,则与required操作类似;
前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。
它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager)
在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解是不会生效的