zoukankan      html  css  js  c++  java
  • @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
    
    不会,我可以学;落后,我可以追赶;跌倒,我可以站起来!
  • 相关阅读:
    /dev/null
    useradd
    linux防火墙
    安装ntp服务同步服务器时间
    使用WTM框架项目的部署遇到的问题及解决方式
    .net5 winform 打开文件夹
    maven打包命令
    url.openconnection() 设置超时时间
    java判断http地址是否连通
    解决 curl: (35) Encountered end of file
  • 原文地址:https://www.cnblogs.com/xiaoshahai/p/15125750.html
Copyright © 2011-2022 走看看