• springboot事务中的一些坑


    springboot开启声明式事务方式

    • 在Application启动类中加入注解@EnableTransactionManagement(mode = AdviceMode.PROXY)
    • 在需要加入事务的方法上加入注解@Transactional
    • @Transactional(rollbackFor = RollbackException.class) 抛出指定异常时回滚
        /**
         * <p>
         *      (rollbackFor = RollbackException.class) 抛出自定义异常时,回滚事务。
         * </p>
         * @throws RollbackException
         */
        @Override
        @Transactional(rollbackFor = RollbackException.class)
        public void insertThenRollback() throws RollbackException {
            jdbcTemplate.execute("INSERT INTO Student (NAME) VALUES ('Tom')");
            throw new RollbackException();
        }
    

    常见问题

    例如有这个实现类StudentServiceImpl:

    @Component
    public class StudentServiceImpl implements StudentService {
    
        /**
         * <p>
         *      (rollbackFor = RollbackException.class) 抛出自定义异常时,回滚事务。
         * </p>
         * @throws RollbackException
         */
        @Override
        @Transactional(rollbackFor = RollbackException.class)
        public void insertThenRollback() throws RollbackException {
            jdbcTemplate.execute("INSERT INTO Student (NAME) VALUES ('BBB')");
            throw new RollbackException();
        }
        
            /**
         * <p>
         *      spring的事务是通过aop进行代理增强的。
         *      这里是在类的内部直接执行方法调用,并没有调用代理类来进行方法调用,所以这里事务不会回滚。
         * </p>
         *
         * @throws RollbackException
         */
        @Override
        public void invokeInsertThenRollback1() throws RollbackException {
            insertThenRollback();
        }
        
    }
    

    上面的insertThenRollback()回回滚事务,invokeInsertThenRollback1()调用了insertThenRollback()方法但是不会回滚事务,这是为什么呢?
    这是因为spring的事务是通过aop进行代理增强的,但这里是在类的内部直接执行方法调用,并没有调用代理类来进行方法调用,所以这里事务不会回滚。

    解决办法

    • 第一种方法:通过AopContext.currentProxy()获取当前类的代理对象。
        /**
         *
         * 通过AopContext.currentProxy()获取当前类的代理对象
         *
         * @throws RollbackException
         */
        @Override
        public void invokeInsertThenRollback2() throws RollbackException {
            ((StudentService) (AopContext.currentProxy())).insertThenRollback();
        }
    
    • 第二种方法:把自己的实例注入进来,让spring为我们创建代理。
        //把自己的实例注入进来
        @Autowired
        private StudentService studentService;
        
        
        /**
         * 把自己的实例注入进来
         * @throws RollbackException
         */
        @Override
        public void invokeInsertThenRollback3() throws RollbackException {
            studentService.insertThenRollback();
        }
    
  • 相关阅读:
    sqoop基本命令
    sqoop-介绍及安装
    HBase与Hive的集成操作
    Phoenix简介及操作
    HBase-Rest API操作
    HBase-Java Native API操作
    HBase-shell操作
    HBase-基本架构
    HBase-物理模型
    HBase-集群安装
  • 原文地址:https://www.cnblogs.com/monkjavaer/p/11461946.html
Copyright © 2020-2023  润新知