天天看點

@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();
   }
}

           
異常被捕獲了,是以事務未生效
               

不會,我可以學;落後,我可以追趕;跌倒,我可以站起來!

上一篇: 02 基本介紹