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

这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB。

根据 MySQL 的官方文档:

MySQL :: MySQL 8.0 Reference Manual :: 16.1 Setting the Storage Engine

从 MySQL 5.5.5 开始的默认存储引擎是:InnoDB,之前默认的都是:MyISAM,所以这点要值得注意,底层引擎不支持事务再怎么搞都是白搭。

2、需要开启事务的方法所在的对象没有交由Spring管理

它没有交由Spring管理,Spring也就不会对他进行增强处理

3、方法不是Public

在进行增强器匹配时,调用getTransactionAttribute()方法,在这个方法中又会调用computeTransactionAttribute()方法,此方法中会进行注解解析,只有当前方法是public,才会进行解析,否则直接返回null

4、自身调用的问题

@Service
public class MyService {
    
    @Autowired
    private MyService myService; // 此时注入的就是代理对象了
    
    @Transactional
    public void test1(){
        System.out.println("我是MyService1中一个方法");
        test2();
    }

    // Propagation.NEVER已经开启事务就抛异常
    @Transactional(propagation = Propagation.NEVER)
    public void test2(){
        System.out.println("我是测试事务异常的");
        int i = 10 / 0;
    }

}

跟据结果可以看出并没有抛出异常,也就是说 @Transactional没有起到效果:

因为此时调用test2()方法的this是被代理对象本身,而不是代理对象,所以spring也就无法在调用test2()方法时进行拦截,检查事务。

解决办法:

①自己注入自己:

@Autowired
private MyService myService; // 此时注入的就是代理对象了

myService.test2(); // 就是调用代理对象的方法了

②再创建一个类,交给spring管理,将方法放到此类中,注入该类对应的bean,调用bean的方法

5、当前数据源没有配置事务管理器

直接报错了,因为是利用事务管理器来创建连接的

6、主动支持以非事务的方式运行

比如:


以非事务方式运行,如果当前存在事务,则把当前事务挂起


int PROPAGATION_NOT_SUPPORTED = 4;

7、在事务方法内部对异常进行了捕获,没有抛出

// @Service public class OrderServiceImpl implements OrderService {

    @Transactional
    public void updateOrder(Order order) {
        try {
            // update order
        } catch {
            .......// 没有throw
        }
    }
}

8、不是RuntimeException或者Error

只有异常是RuntimeException和Error类型的,才会进行回滚处理

解决:

可以手动指定想要处理的异常类型

@Transactional(rollbackFor = Exception.class)

配置仅限于 Throwable 异常类及其子类

如有问题欢迎指正......