HelloCoder HelloCoder
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
  • 《k8s学习心得》
随笔
关于作者
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
  • 《k8s学习心得》
随笔
关于作者
  • 《LearnJavaToFindAJob》

    • 导读

    • 【初级】6~12k档

      • Java基础

      • JVM

      • 牛客网题库

      • MySQL

      • Linux

      • 计算机网络

      • 操作系统

      • Java框架

        • Hibernate面试题
        • Mybatis面试题
        • Redis面试题
        • Servlet的生命周期
        • Spring

          • SpringMVC中Controller是线程安全的吗?
          • SpringMVC面试题
          • Spring事务失效的场景有哪些?
          • Spring的传播行为有哪些?隔离级别有哪些?
          • Spring面试题
        • SpringBoot

        • SpringCloud

        • Spring拦截器和过滤器有什么区别?
        • Struts面试题
    • 【中级】12k-26k档

    • 【高级】26k+档

    • 大厂面试题

    • 求职建议

    • 面经

  • LearnJavaToFindAJob
  • 【初级】6~12k档
  • Java框架
  • Spring
#Spring #事务失效 #场景有哪些
HaC
2022-06-02
目录

Spring事务失效的场景有哪些?

# spring的事务失效场景有哪些?

在spring框架中,使用事务还是很简单的,只需要在对应的方法上加上@Transactional注解即可,但并不是加了注解事务就会生效,开发者在使用该注解的时候,需要注意的地方还是很多的,所以这也是面试中经常会问到的。

简单总结一下spring事务失效的场景:

1、注解@Transactional配置的方法非public权限修饰;

2、注解@Transactional所在类中,注解修饰的方法被类内部方法调用;

3、业务代码抛出异常类型非RuntimeException,事务失效;

4、业务代码中存在异常时,使用try…catch…语句块捕获,而catch语句块没有throw new RuntimeExecption异常;(相对于正常处理了)

5、注解@Transactional中Propagation属性值设置错误即Propagation.NOT_SUPPORTED(一般不会设置此种传播机制),或者使用PROPAGATION_REQUIRES_NEW起一个新的事务,旧的事务报错了回滚,新的事务没有回滚。

6、mysql关系型数据库不支持,且存储引擎是MyISAM而非InnoDB,则事务会不起作用(基本开发中不会遇到);

下面详细来说明一下事务的场景:

# 1、非public权限修饰方法

spring事务也是通过动态代理来实现的,它在方法进来的时候判断当前method是否是public。(是spring对非public方法的过滤,其实jdk、cglib还是可以为非public方法生成代理对象的)

如果要用在非 public 方法上,可以开启 AspectJ 代理模式

# 2、内部方法调用

@Service
public class OrderServiceImpl implements OrderService {
    @Transactional
    public void update(Order order) {
        updateOrder(order);
    }
   // @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateOrder(Order order) {
        // update order
    }
}

为什么会失效呢?其实原因很简单,Spring在扫描Bean的时候会自动为标注了@Transactional注解的类生成一个代理类(proxy),当有注解的方法被调用的时候,实际上是代理类调用的,代理类在调用之前会开启事务,执行事务的操作,但是同类中的方法互相调用,相当于this.updateOrder(),此时的updateOrder方法并非是代理类调用,而是直接通过原有的Bean直接调用,所以注解会失效。

即使被调用方法用了 Propagation.REQUIRES_NEW也不会生效。

解决方法:

@Service
public class OrderServiceImpl implements OrderService {
     @Autowired
    OrderServiceImpl orderService;
    
    @Transactional
    public void update(Order order) {
        orderService.updateOrder(order);
    }
   // @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateOrder(Order order) {
        // update order
    }
}

# 3、非RuntimeException

事务默认的回滚的异常是RuntimeException,如果是抛出非RuntimeException ,是不会回滚的。

当然你也可以指定自定义的异常回滚。

# 4、try…catch捕获

try…catch语句捕获后,就是相当于的异常处理了,这也是开发中要注意的,一不小心调用的方法有异常处理,捕获的时候也没有抛出,即使出错了,也不会回滚事务。

# 5、Propagation属性值设置错误

PROPAGATION_REQUIRED :如果当前没有事务,就新建一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。

除此之外,还有很多属性,如果使用PROPAGATION_REQUIRES_NEW,表示新起一个事务,这样当两个事务就是不相干了,出错也会回滚。

# 6、mysql不支持事务

从 MySQL 5.5.5 开始的默认存储引擎是:InnoDB,之前默认的都是:MyISAM,所以这点要值得注意,底层引擎不支持事务,spring也没有办法,毕竟spring的事务就是建立在数据库的事务之上的。

#Spring#事务失效#场景有哪些
上次更新: 2026-06-21 17:47:53
最近更新
01
MySQL支持的锁有哪些
06-21
02
HTTP 是不保存状态的协议, 如何保存用户状态
06-21
03
WebSocket、短轮询、长轮询的区别
06-21
更多文章>
Theme by Vdoing | Copyright © 2020-2026 HaC
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式