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:html

@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进行代理加强的,但这里是在类的内部直接执行方法调用,并无调用代理类来进行方法调用,因此这里事务不会回滚。java

解决办法

  • 第一种方法:经过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();
    }

原文出处:https://www.cnblogs.com/monkjavaer/p/11461946.htmlspring

相关文章
相关标签/搜索