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
    
    不会,我可以学;落后,我可以追赶;跌倒,我可以站起来!
  • 相关阅读:
    FineBI与power BI,一个是国外风生水起的微软巨头,一个是方兴未艾的国产BI厂商领导者
    Linux下的crontab定时执行任务命令详解举例
    手把手教你搭建SSH框架(Eclipse版)
    一、连接池的定义
    centos安装sftp服务win搭建 sftp 服务器
    前往阿里云的企业优惠活动页面
    世界可能是思想最为混乱的时候,无论你说什么
    python面向对象编程class1
    Python 文件I/O 文件读写模式r,r+,w,w+,a,a+的区别
    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里
  • 原文地址:https://www.cnblogs.com/xiaoshahai/p/15125750.html
Copyright © 2011-2022 走看看