1. 数据库引擎不支持事务

以 MySQL 为例,MyISAM存储引擎不支持事务, InnoDB 引擎支持事务。

2. 异常被catch

执行以下测试方法,数据成功插入,调用 test 方法没有回滚。

@Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void test(CustomerDO customerDO) {
        mapper.insert(customerDO);
        try {
            int i = 1 / 0;
        } catch (Exception e) {
            log.info("", e);
        }
    }

3. 异常抛出类型错误

异常抛出类型错误,事务回滚的默认级别是 RuntimeException,抛出的异常必须是 RuntimeException 或它的子类。

抛出的异常是 RuntimeException 时,调用 test 方法回滚成功:

@Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void test(CustomerDO customerDO) throws Exception {
        mapper.insert(customerDO);
        throw new RuntimeException("234334334");
    }

抛出的异常是 Exception 时,是RuntimeException的父类,不被识别,调用 test 方法回滚失败:

@Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void test(CustomerDO customerDO) throws Exception {
        mapper.insert(customerDO);
        throw new Exception("234334334");
    }

解决办法,指定回滚的异常 rollbackFor = Exception.class,调用 test 方法回滚成功:

@Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void test(CustomerDO customerDO) throws Exception {
        mapper.insert(customerDO);
        throw new Exception("234334334");
    }

4. 本类方法调用

本类方法调用,会用 this 关键字,没有经过Spring的代理类去调用此方法。

如下使用this关键字,调用 test 方法回滚失败:

@Override
    public void test(CustomerDO customerDO) throws Exception {
        test1(customerDO);
    }
    
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void test1(CustomerDO customerDO) throws Exception {
        mapper.insert(customerDO);
        int i = 1 / 0;
    }

如下调用 test 方法回滚成功,REQUIRES_NEW 失效:

@Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void test(CustomerDO customerDO) throws Exception {
        test1(customerDO);
        int i = 1 / 0;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void test1(CustomerDO customerDO) throws Exception {
        mapper.insert(customerDO);
    }

5. 没有被Spring管理

没有被Spring管理,无法使用Spring的事务,事务自然不起作用。

一般工程中不会有这种错误,一般 Service 方法是注入到 Controller 里面的。