Spring中@Transactional事务失效原因

导读:本篇文章讲解 Spring中@Transactional事务失效原因,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

@Transactional 注解的作用就是保证方法内的多个数据库操作具有事务特性,即要么都成功提交,要么都失败回滚。但是错误的使用会导致事务失效,以下是总结的九种可能发生事务失效的原因

1、@Transactional 用在非 public 修饰的方法上

事务拦截器在目标方法执行前后进行拦截,内部会调用方法来获取 Transactional 注解的事务配置信息,调用前会检查目标方法的修饰符是否为 public,不是 public 则不会获取 @Transactional 的属性配置信息。


2、@Transactional 用于接口上

虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。


3、@Transactional 注解属性 propagation 设置以下三种可能导致无法回滚

SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。


4、同一类中加 @Transactional 方法被无 @Transactional 的方法调用,事务失效

如果在同一个类中的不同方法调用中,A方法调用B方法,A中无事务,B中有事务,那事务不会生效。因为Spring采用动态代理实现对bean的管理和切片,它为每个class都会生成一个代理对象。只有在代理对象之间调用时,可以触发切面逻辑。而同一个 class 中,方法A调用方法B,且方法A无事务,调用的是原对象的方法,而不是通过代理对象,因此Spring无法切换到这次调用,也就无法通过注解保证事务性了。


5、@Transactional 方法内异常被捕获

事务在调用业务方法之前就开始了,业务方法执行完毕之后才执行提交或回滚,而事务是否执行取决于是否抛出运行异常。如果抛出了运行异常并在你的业务方法中没有 catch 到的话,事务就会回滚。但是如果异常被用户代码手动捕获了的话,那这个异常就不会抛给 spring 切面,那整个事务会被正常提交。如果非要catch就一定要抛出 throw new RuntimeException(),或者注解中指定抛异常类型 @Transactional(rollbackFor=Exception.class)


6、数据库不支持事务

也可能是数据库不支持事务,比如 MySQL 使用的 MyISAM 存储引擎


7、@Transactional 的注解 rollbackFor 属性设置错误

rollbackFor 默认是 RuntimeException 和 Error 及子类抛出,就会回滚;如果 rollbackFor 指定了异常类型,那只有指定的异常及子类发生才会回滚


8、Spring 的配置文件中未配置开启事务注解

<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"/>

9、没有引入 jbdc 或 jpa 包,不会开启事务

Spring Boot 引入了 jbdc 或 jpa 包,会默认开启事务注解。若未引入这两个包,需要在启动类加上 @EnableTransactionManagement 进行配置

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/98652.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!