@Transactional注解不起作用解决办法及原理分析

@Transcational 失效场景--转载

第一种
Transcation注解用在非public方法上时,注解将会失效
    
比如@Transcation修饰一个default访问符的方法
    

@Component
public class TestServiceImpl {
    @Resource
    TestMapper testMapper;
    
    @Transactional
    void insertTestWrongModifier() {
        int re = testMapper.insert(new Test(10,20,30));
        if (re > 0) {
            throw new NeedToInterceptException("need intercept");
        }
        testMapper.insert(new Test(210,20,30));
    }

}

测试用例
@Component
public class InvokcationService {
    @Resource
    private TestServiceImpl testService;
    public void invokeInsertTestWrongModifier(){
        //调用@Transactional标注的默认访问符方法
        testService.insertTestWrongModifier();
    }
}

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
   @Resource
   InvokcationService invokcationService;

   @Test
   public void  testInvoke(){
      invokcationService.invokeInsertTestWrongModifier();
   }
}
问题分析
以上的访问方式,导致事务没开启,此时如果出现异常也不会回滚,如果将事务方法修改为public,事务就会正常开启
第二种
本类内部方法标注@transcation,这种情况下事务也不会生效
    

@Component
public class TestServiceImpl implements TestService {
    @Resource
    TestMapper testMapper;

    @Transactional
    public void insertTestInnerInvoke() {
        //正常public修饰符的事务方法
        int re = testMapper.insert(new Test(10,20,30));
        if (re > 0) {
            throw new NeedToInterceptException("need intercept");
        }
        testMapper.insert(new Test(210,20,30));
    }


    public void testInnerInvoke(){
        //类内部调用@Transactional标注的方法。
        insertTestInnerInvoke();
    }

}
测试案例

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

   @Resource
   TestServiceImpl testService;

   /**
    * 测试内部调用@Transactional标注方法
    */
   @Test
   public void  testInnerInvoke(){
       //测试外部调用事务方法是否正常
      //testService.insertTestInnerInvoke();
       //测试内部调用事务方法是否正常
      testService.testInnerInvoke();
   }
}

问题分析
上述情况使用测试代码,事务不会开启,如果用外部方法调用则会开启事务
第三种
事务方法内部捕获异常,没有抛出异常,导致事务不会生效
    
@Component
public class TestServiceImpl implements TestService {
    @Resource
    TestMapper testMapper;

    @Transactional
    public void insertTestCatchException() {
        try {
            int re = testMapper.insert(new Test(10,20,30));
            if (re > 0) {
                //运行期间抛异常
                throw new NeedToInterceptException("need intercept");
            }
            testMapper.insert(new Test(210,20,30));
        }catch (Exception e){
            System.out.println("i catch exception");
        }
    }
    
}
测试案例

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

   @Resource
   TestServiceImpl testService;

   @Test
   public void testCatchException(){
      testService.insertTestCatchException();
   }
}

问题分析
异常被捕获了,所以事务未生效
相关资料
https://blog.csdn.net/qq_20597727/article/details/84868035
对前三种情况的源码解析
https://blog.csdn.net/qq_20597727/article/details/84900994
不会,我可以学;落后,我可以追赶;跌倒,我可以站起来!
原文地址:https://www.cnblogs.com/xiaoshahai/p/15125750.html