• 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();
        }
    
  • 相关阅读:
    FPGrowth 实现
    数据库事务的4个特性ACID
    redis简介(keeper实时报表的基本部分)
    HADOOP中的CRC数据校验文件
    潜在语义分析
    AdaBoost 算法
    cocosBuilder生成cbbi文件,绑定到cocos2d-x
    C++继承模型
    Android应用经典主界面框架之中的一个:仿QQ (使用Fragment, 附源代码)
    从今天開始学习iOS开发(iOS 7版)--实现一款App之Foundation框架的使用
  • 原文地址:https://www.cnblogs.com/monkjavaer/p/11461946.html
Copyright © 2020-2023  润新知