本站消息

站长简介/公众号


站长简介:逗比程序员,理工宅男,前每日优鲜python全栈开发工程师,利用周末时间开发出本站,欢迎关注我的微信公众号:幽默盒子,一个专注于搞笑,分享快乐的公众号

  价值13000svip视频教程,java大神匠心打造,零基础java开发工程师视频教程全套,基础+进阶+项目实战,包含课件和源码

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2021-05(14)

2021-06(54)

2021-07(10)

2021-08(60)

2021-09(21)

为啥Spring事务失效了,你踩坑了吗?

发布于2021-05-29 20:18     阅读(678)     评论(0)     点赞(12)     收藏(1)


  hello,慕仔们,我们又见面了。图片图片图片前段时间小慕做的智慧社区门禁服务的业务中恰好遇上了事务失效的场景,于是就有了今天的这篇文档总结,避免让慕仔们踩坑。图片图片

 今天我们不聊微服务架构下的分布式事务,只谈单体应用系统下的事务,那到底哪些情况下会导致事务失效呢?咱们现在就来唠嗑唠嗑吧!

   

    

1. 底层数据库引擎不支持事务

以MySQL为例,MyISAM引擎不支持事务操作,InnoDB引擎支持事务,MySQL从5.5.5开始默认的引擎是InnoDB,之前的版本默认的都是MyISAM,所以这个要注意。

 

2. 被@Transactional 注解修饰的方法为非public类型

如果被@Transactional注解修饰的方法,修饰符非public或者被final修饰,则事务会失效,因为AOP没办法为这样的方法生成一个代理,自然事务就无法生效。这个在Spring的官方文档里面也有说明。

 

3. 异常被吃掉了

如果异常被 catch 住,那事务也是会失效呢,伪代码如下

@Transactionalpublic void test(){  try{    //插入一条数据    insertData();    //更改一条数据    updateData();  }catch(Exception e){    log.error("异常被捕获,事务失效",e);  }}

 

 

4. 异常抛出类型错误

@Transactional 注解有个属性:rollbackFor,这个属性可以设置想要回滚的异常类型,那它默认的异常类型是什么?立即回答:RuntimeException,太棒了。

如果说我们没有设置这个属性,而且抛出的异常比这个大,那么事务就不会回滚,例如:

@Transactionalpublic void test(){  try{    //插入一条数据    insertData();    //更改一条数据    updateData();  }catch(Exception e){    // 这个时候事务就不会回滚,    throw new Exception("操作失败!");  }}

 

5. 本类方法调用

这一个应该是最容易踩坑的了,也是小慕踩坑的地方,先来看两段伪代码:

代码一:

@Servicepublic class TestServiceImpl implements TestService {   public void testA() {        // 查询数据,并进行一些判断        // 调用本类的另外一个方法        testB();    }
  1. @Transactional
  2.   public void testB(Test test) {
// update test }}

小慕提问图片:testA()方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 testB() 方法,testB() 方法上的事务管用吗?

 

代码二:

@Servicepublic class TestServiceImpl implements TestService {
  1. @Transactional
  2.   public void testA() {
// 查询数据,并进行一些判断 // 调用另外一个方法 testB();
  1. }
  2. @Transactional(propagation = Propagation.REQUIRES_NEW)
  3. public void testB(Test test) {
// update test }}

小慕提问图片:在 testA() 方法上加了 @Transactional,testB() 的注解上加了 REQUIRES_NEW 新开启一个事务,那么新开的事务管用么?

 

立即推,以上两段代码的事务都不生效,答对了吧,答对的小伙伴手动@我,找我领红包,图片图片图片

为啥会失效,因为他们是本类的方法直接调用,这个时候会用this关键字,没有经过 Spring 的代理类去调用此方法,从而没有开启事务管理,默认只有在外部调用事务才会生效。

 

总结::加事务注解的方法给本类里面的方法调用,事务不生效!

 

话又说回来了,那怎么解决这个问题呢?小慕提供3种解决方案

解法一::最直白的就是把方法拆出来,放在两个类里面(Spring推荐的一种方式);

 

解法二:在类里面注入自己,用注入的对象再调用另外一个方法,这个不太优雅;

 

解法三:在Spring的配置里面增加一段配置  :

   <aop:aspectj-autoproxyexpose-proxy="true"/>

 

 

6、没有被spring管理

当这个类只是一个普通类,没有被spring管理成为一个Bean对象,那它很自然的就不能使用spring提供的事务管理了,事务自然就不生效。

 

半山腰总是最挤的,你得去山顶上瞅瞅,拜拜图片图片图片

好,今天的内容就分享到这里了,你们一定要变优秀哦,我们下期再见。

现在公众号迁移到这个啦, 不要迷路了,慕仔们,加油哦!

       接下来的一段时间,我会专注Java技术栈,计算机网络,数据结构和算法,操作系统,设计模式,计算机组成原理,数据库原理,设计模式来做分享,欢迎你们和我一起学习,一起提高,Fighting!

原文链接:https://blog.csdn.net/qq_40241957/article/details/117326069



所属网站分类: 技术文章 > 博客

作者:我是不是很美

链接:http://www.javaheidong.com/blog/article/207305/4714ee036bf736484371/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

12 0
收藏该文
已收藏

评论内容:(最多支持255个字符)