@Transactional失效原因分析

概述

上次分享了在使用自定义注解形式的@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注解进行修饰。
@Transactional失效原因分析_第1张图片

==解决方法:==

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

解决方法已经在文章分享过了,这里不再赘述。

你可能感兴趣的:(注解失效)