转载自:spring事务失效的原因
spring事务失效的原因是什么?我们如何解决?下面我们一起来了解一下!
Spring失效原因
事务失效的原因和解决方案
服务没有开启事务管理
原因:没有开启事务管理,Spring无法创建事务代理对象,导致事务不生效
解决方案:springBoot服务在application上添加@EnableTransactionManagement注解
@SpringBootApplication
@EnableTransactionManagement
public class A{
public static void main(String[] args) {
SpringApplication.run(A.class, args);
}
}
2.Service没有交由spring进行管理
原因:Spring事务是由AOP机制实现的,也就是说从Spring IOC容器获取bean时,Spring会为目标类创建代理,来支持事务的。但是service没有添加@Service被注解,spring无法管理当前service,也就无法支持事务
解决方案:service上添加@Service注解
@Service
public class DemoServiceImpl{
//业务方法。。。。。。。
}
3.使用了错误的事务传播机制
原因:Propagation.NOT_SUPPORTED传播特性不支持事务。
解决方案:选择正确的事务传播机制
@Service
public class DemoServiceImpl{
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public String baseInfo(String param) {
//业务逻辑。。。。。。。
return "test";
}
}
4.同一个类中,方法内部调用
@Service
public class DemoServiceImpl{
public void A(){
B();
}
@Transactional
public void B(){
//处理业务逻辑
}
}
DemoServiceImpl中方法A中调用了方法B,方法B加了@Transactional注解,但是方法B事务处理仍失效了
失效原因:事务是通过Spring AOP代理来实现的,而在同一个类中,一个方法调用另一个方法时,调用方法直接调用目标方法的代码,而不是通过代理类进行调用。所以调用目标executeAddTianLuo方法不是通过代理类进行的,因此事务不生效。
解决方案:新建一个类,将方法放在不同类中
5.方法的访问权限不是public
@Service
public class DemoServiceImpl{
@Transactional
private void A(){
//处理业务逻辑
}
}
原因:spring事务方法A的访问权限不是public,事务不生效,因为Spring事务是由AOP机制实现的,AOP机制的本质就是动态代理,而代理的事务方法不是public的话,computeTransactionAttribute()就会返回null,spring就不再给方法添加事务属性 解决方法:将private 改为public
查看源码**************************************************************
/**
* Same signature as {@link #getTransactionAttribute}, but doesn't cache the result.
* {@link #getTransactionAttribute} is effectively a caching decorator for this method.
* <p>As of 4.1.8, this method can be overridden.
* @since 4.1.8
* @see #getTransactionAttribute
*/
@Nullable
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;
}
6.事务方法被final、static关键字修饰
@Service
public class DemoServiceImpl{
@Transactional
public final void A(){
//处理业务逻辑
}
}
原因:如果一个方法被声明为final或者static,则该方法不能被子类重写,也就是说无法在该方法上进行动态代理,这会导致Spring无法生成事务代理对象来管理事务。
解决方法:事务方法不要用final或者static修饰。
7。数据库的存储引擎不支持事务
Spring事务的底层,还是依赖于数据库本身的事务支持。如果您使用的是mysql数据库,且数据库没有使用InnoDB存储引擎,那么事务会失效,另Spring事务的底层,还是依赖于数据库本身的事务支持。
解决办法:使用支持事务的引擎(mysql使用InnoDB)
8.方法中使用了try{}catch(Exception e){}捕获了异常
@Service
public class DemoServiceImpl{
@Transactional
public final void A(){
Try{
//处理业务逻辑
}catch(Exception e){
//异常处理逻辑
}
}
}
原因:事务方法中如果我们使用try{}catch(Exception e){}捕获了异常,就会引起事务失效
解决办法:去掉try{}catch(Exception e ){}或者在 catch中抛出有效的异常
9.手动抛出了非RuntimeException异常
@Service
public class DemoServiceImpl{
@Transactional( rollbackFor = Exception)
public final void A(){
Try{
//处理业务逻辑
}catch(Exception e){
throw new Exception(“处理异常”);
}
}
}
原因:Spring事务默认处理RuntimeException,对应手动抛出的非RuntimeException会导致事务失效
解决办法:我们可以配置@Transactional( rollbackFor = Exception)