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
异常类及其子类
如有问题欢迎指正......