SpringBoot默认开启事务,也提供了@Transactional帮助我们进行事务管理,使用起来简单方便。不过在实际开发中有时会遇到事务不生效的情况,总结一下,以备不时之需。
1.访问权限控制
Java中有四种访问权限:public、protected、default和private,而@Transactional是通过AOP实现的事务管理,并通过动态代理来调用被事务管理的方法,被代理的方法必须是public修饰的,否者事务不生效。(同理,final、static修饰的方法也不会生效)
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// Second try is the transaction attribute on the target class.
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
// Fallback is to look at the original method.
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
2.异常未被抛出
SpringBoot中事务回滚需要方法抛出声明的异常,如果方法中捕获了异常或者未抛出声明的异常,事务就不会回滚。
3.方法未被事务管理或事务传播机制选择非事务
4.多线程操作或使用异步操作
5.关闭SpringBoot的事务管理或创建的对象不被Spring容器管理
6.底层数据库不支持事务