1. 未启用 Spring 事务管理功能或 bean 没有被 spring 管理
2. @Transactional 修饰的方法非 public 或被 final、static 修饰
3. 同类的方法 A 直接调用同类的事务方法 B
spring 事务是通过 Spring AOP 实现的, 对需要 spring 管理事务的 bean 生成了代理对象,然后通过代理对象拦截了目标方法的执行,在方法前后 添加了事务的功能,所以必须通过代理对象调用 目标方法的时候,事务才会起效。如果方法 A 直接调用方法 B 则是 this 调用,即该类的类对象,就不是代理对象。可以通过
Service类中注入自己,或者通过AopContext.currentProxy()获取代理对象来解决。
4. 抛出的异常类型错误
在业务方法进行异常抛出,spring 会自动对事务进行回滚,那么问题来了,抛出哪些异常 spring 会回滚事务呢?默认情况下,spring 遇到 RuntimeException 和 Error 的事务才会回滚。因为 spring 认为 RuntimeException 和 Error 是不可预期的错误,而受检异常是可预期的错误,可以通过业务逻辑即可解决。
当然也可以自定义回滚异常类型@Transactional(rollbackFor = {异常类型列表})
5. 异常被捕获处理
spring 感知到指定异常被抛出才会进行回滚,如果在方法内部捕获处理掉异常,事务就不会回滚
|
|
正确做法是捕获处理掉异常后抛出来,如下:
|
|
6. 事务操作和@Transactional 方法不在同一线程
|
|
7. 事务传播行为设置不对
spring 默认事务传播行为默认是**required,事务方法 A 内部调用事务方法 B,**如果方法 A 存在事务则方法 B 加入方法 A 的事务,否则创建新事务。如果非事务方法 A 调用事务方法 B,事务传播级别为 NOT_SUPPORT,因为方法 A 当前不存在事务,则方法 B 虽然有@Transactional 注解,但仍然以非事务去执行。