🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## @Transactional 注解可以作用于哪些地方 1. 作用于类:当把@Transactional 注解放在类上时,表示所有该类的public方法都配置相同的事务属性信息。 2. 作用于方法:当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息。 3. 作用于接口:不推荐这种使用方法,因为一旦标注在Interface上并且配置了Spring AOP 使用CGLib动态代理,将会导致@Transactional注解失效 ## @Transactional 失效场景 1. @Transactional 应用在非 public 修饰的方法上 必须在代理类里重写带注解方法以添加开启事务、提交事务的代码。从这个角度来说,private方法不能被继承,final方法不能被重写,static方法和继承不相干,所以它们3个的事务不起作用。Spring选择让protected方法和package方法不支持事务 2. @Transactional 注解属性 propagation 设置错误 TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。 TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。比如 IO操作的错误都不会回滚 3. @Transactional 注解属性 rollbackFor 设置错误 Spring默认抛出了未检查unchecked异常(继承自 RuntimeException的异常)或者 Error才回滚事务. 4. 同一个类中方法调用,导致@Transactional失效 A没有事务, A调用同个类的B, 这时候B的事务也不会有效果. A没有事务调用其他类的C方法, C的事务会有效果, A不会有效果 5. 异常被你的 catch“吃了”导致@Transactional失效 Spring 事务使用AOP实现, 不抛异常, 导致AOP异常通知无法回滚, 如果事务注解里的某段代码报错不想影响已经执行的代码, 就可以使用try catch 将其包裹. 6. 数据库引擎不支持事务 (5.5版本之前)低版本的 MySQL以前都是用的MySQL自己的存储引擎 MyISAM, 这个不支持事务, 现在的MySQL默认都是使用的第三方存储引擎InnoDB, 这个是支持事务的 7. 方法不在同一个大的事务下 之前遇到过同事在controller 方法A直接调用了俩个其他controller层对应service层的方法B和方法C, B 和 C 是有正确使用注解, 但是方法C报错, 方法B的事务没有回滚 , 原因就是B和C是各自不同的事务, 当方法B执行完之后, 其事务也就结束了, 当后续的方法C报错时, 只会影响C的事务回滚. controller 层应该只调用自己对应的service层, 由自己的service层再去调用其他service层的方法。