实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机制;好多小伙伴可能只是简单了解一下,遇到事务失效的情况,便会无从下手,溪源此篇文章给大家整理了一下常见Spring事务失效的场景,希望开发过程尽量避免踩坑,造成时间精力的浪费。溪源按照最基本的使用方式以及常见失效场景优先级整理,先简单介绍一下具体失效场景:
1. 注解@Transactional配置的方法非public权限修饰;
2. 注解@Transactional所在类非Spring容器管理的bean;
3. 注解@Transactional所在类中,注解修饰的方法被类内部方法调用;
4. 业务代码抛出异常类型非RuntimeException,事务失效;
5. 业务代码中存在异常时,使用try…catch…语句块捕获,而catch语句块没有throw new RuntimeExecption异常;(最难被排查到问题且容易忽略)
6. 注解@Transactional中Propagation属性值设置错误即Propagation.NOT_SUPPORTED(一般不会设置此种传播机制)
7. mysql关系型数据库,且存储引擎是MyISAM而非InnoDB,则事务会不起作用(基本开发中不会遇到);下面基于以上场景,溪源给小伙伴们详细解释;
· 非public权限修饰参考Spring官方文档介绍,摘要、译文如下:
When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.
译文
使用代理时,您应该只将@Transactional注释应用于具有公共可见性的方法。如果使用@Transactional注释对受保护的、私有的或包可见的方法进行注释,则不会引发错误,但带注释的方法不会显示配置的事务设置。如果需要注释非公共方法,请考虑使用AspectJ(见下文)。
简言之:@Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式。目前,如果@Transactional注解作用在非public方法上,编译器也会给与明显的提示,如图: