@Transactional失效原因分析

本文通过三个具体场景,探讨了Spring框架中@Transactional注解在不同情况下是否有效,特别是当方法内部调用自身类中的其它方法时,事务管理可能出现的失效问题,并提出了相应的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述
上次分享了在使用自定义注解形式的@redis做缓存时,失效的原因。今天探讨一下Spring的事务管理@Transactional在同样的情况下是否会失效。

实例
经过个人验证,在一个类中的方法调用时,被调用的方法如果有事务管理,那么事务管理会失效。
情况1
以下代码执行时,数据插入数据库不成功,因为insert1()开启了事务,会回滚:
//开启事务代码
@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
    @Override
    public void insert1(CountryInfo countryInfo) {
        countryInfoMapper.addCountryInfo(countryInfo);
        throw new RuntimeException("测试插入事务");
    }
//测试代码:
@Test
  public void insert1(){
      CountryInfo c=new CountryInfo();
      c.setCountryCode("U6");
      c.setCountryLanguage("en1");
      c.setCountryName("us1");
      c.setCountryNameZh("chus1");
      countryService.insert1(c);
  }
情况2
以下代码执行时,数据插入数据库不成功,尽管insert1()失效了,但是insert2()开启了事务。
@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
    @Override
    public void insert1(CountryInfo countryInfo) {
        countryInfoMapper.addCountryInfo(countryInfo);
        throw new RuntimeException("测试插入事务");
    }


    @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
    @Override
    public void insert2(CountryInfo countryInfo) {
        this.insert1(countryInfo);
        //throw new RuntimeException("测试插入事务");
    }
//测试代码:
@Test
  public void insert2(){
      CountryInfo c=new CountryInfo();
      c.setCountryCode("U8");
      c.setCountryLanguage("en2");
      c.setCountryName("us2");
      c.setCountryNameZh("chus2");
      countryService.insert2(c);
  }
情况3
以下代码执行时,数据插入数据库成功,因为insert1()事务失效了,而且insert2()没有开启事务,不会回滚
@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
    @Override
    public void insert1(CountryInfo countryInfo) {
        countryInfoMapper.addCountryInfo(countryInfo);
        throw new RuntimeException("测试插入事务");
    }


    //@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
    @Override
    public void insert2(CountryInfo countryInfo) {
        this.insert1(countryInfo);
        //throw new RuntimeException("测试插入事务");
   }
 //测试代码:
 @Test
  public void insert2(){
      CountryInfo c=new CountryInfo();
      c.setCountryCode("U8");
      c.setCountryLanguage("en2");
      c.setCountryName("us2");
      c.setCountryNameZh("chus2");
      countryService.insert2(c);
  }
原因分析
@Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。
默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。

==解决方法:==

[[自定义注解@Redis失效原因分析]]

解决方法已经在文章分享过了,这里不再赘述。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱coding的同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值