zoukankan      html  css  js  c++  java
  • 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();
        }
    
  • 相关阅读:
    第10组 Beta冲刺 (4/5)
    第10组 Beta冲刺 (3/5)
    第10组 Beta冲刺 (2/5)
    第10组 beta冲刺(1/5)
    软工实践个人总结
    第01组 每周小结(3/3))
    第01组 每周小结(2/3)
    第01组 每周小结 (1/3)
    第01组 beta冲刺总结
    第01组 beta冲刺(5/5)
  • 原文地址:https://www.cnblogs.com/monkjavaer/p/11461946.html
Copyright © 2011-2022 走看看