项目中用sprin祝酒词大全g的 @transactional 注解控制事务,使用中时常出现事物不生效的场景,本文仅限于日常项目开发中的点滴整理总结,总结以下几点,以备后续参考排查;可能不全,列举出来希望可以帮助有需要的同学,避免踩坑。
这里以 mysql 为例,其 myisam 引擎是不支持事务操作的,innodb 才是支持事务的引擎,一般要支持事务都会使用 innodb。
根据 mysql 的官方文档:
https://dev.mysql.com/doc/refman/5.5/en/storage-engine-tting.html
从 mysql 5.5.5 开始的默认存储引擎是:innodb,之前默认的都是:myisam,所以这点要值得注意,底层引擎不支持事务是硬伤。
没有被 spring 管理
// @rvice (此注解不能去掉)public class accountrviceimpl implements accountrvice {@transactionalpublic void inr(account account) {// inrt account}}
如果此时把 @rvice 注解注释掉,这个类就不会被加载成一个 bean,那这个类就不会被 spring 管理了,事务自然就失效了。
以下来自于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 raid, but the annotated method does not e醉酒妈妈xhibit the configured transactional ttings. consider the u of aspectj (e below) if you need to annotate non-public methods.
意思就是 @transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以考虑开启 aspectj 代理模式。
看下面代码
@rvicepublic class accountrviceimpl implements accountrvice {public void inrt(account account) {inrtaccount(account);}@transactionalpublic void inrtaccount(account account) {// inrt account}}
inrt方法上面没有加 @transactional 注解,调用有 @transactional 注解的 inrtaccount 方法,inrtaccount 方法上的事务其实是不管用的。
再看下面的代码
@rvicepublic class accountrviceimpl implements accountrvice {@transactionalpublic void inrt(account account) {inrtaccount(account);}@transactional(核工业学院propagation = propagation.requires_new)public void inrtaccount(account account) {// inrt account}}
这次在 inrt 方法上加了 @transactional,inrtaccount 加了 requires_new 新开启一个事务,那么新开的事务管用么?
这两个例子的答案是:不管用!
因为它们发生了自身调用,就调该类自己的方法,而没有经过 spring 的代理类,默认只有在外部调用事务才会生效,这也是老生常谈的经典问题了。
数据源没有配置事物管理器
@beanpublic platformtransactionmanager transactionmanager(datasource datasource) {return new datasourcetransactionmanager(datasource);}
如上面所示,当前数据源若没有配置事务管理器,照样会失效!
@rvicepublic class accountrviceimpl implements accountrvice {@transactionalpublic void inrt(account account) {inrtaccount(account);}@transactional(propagation = propagation.not_supported)public void inrtaccount(account account) {// inrt account}}
propagation.not_supported: 表示不以事务运行,当前若存在事务则挂起,详细的可以参考innodb的事务隔离级别和传播机制。
都主动不支持以事务方式运行了,那事务生效也是白搭!
这个是比较常见的场景
@rvice (此注解不能去掉)public class accountrviceimpl implements accountrvice {@transactionalpublic void inr(account account) {try {// inrt account} catch {}}}
把异常吃了,然后又不抛出来,事务就无法回滚!
@rvice (此注解不能去掉)public class accountrviceimpl implements accountrvice {@transactionalpublic void inr(account account) {try {//除法导数 inrt account} catch {throw new exception("新增错误");}}}
这样事务也是不生效的,因为默认回滚的是:runtimeexception,如果你想触发其他异常的回滚,需要在注解上配置一下,如:
@transactional(rollbackfor = exception.class)
这个配置仅限于 throwable 异常类及其子类。
查阅资料,其他失效的场景需注意:1) 像文件导入数据库,用多线程控制;可参考查询spring 多线程事务的问题 2)springboot+shiro引起事务失效
本文总结了几种事务失效的场景,其实发生最多就是自身调用、异常被吃、异常抛出类型不对这三个了;像文章开头说的那样,本文不一定总结得全,只是根据经验总结常见的事务失效的场景。
到此这篇关于spring事务失效场景的文章就介绍到这了,更多相关spring事务失效场景内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-05 00:57:57,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/5158c48d65d27840e55df609c4fe3cae.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:Spring事务失效场景的详细整理.doc
本文 PDF 下载地址:Spring事务失效场景的详细整理.pdf
留言与评论(共有 0 条评论) |