Spring事务失效的原因分析

一.抛出事务不支持的异常

原理:

Spring事务默认支持RuntimeException异常,抛出的异常为RuntimeException异常及其子类异常事务均可生效,而我们日常常见的异常基本都继承自RuntimeException,所以无需指定异常类型事务也能生效。但若手动抛出Exception异常,而Exception是RuntimeException的父类,会导致事务不生效。

解决方案:

1.指定Spring事务异常捕获类型

@Transactional(rollbackFor = Exception.class)

2.抛出Spring事务支持的异常类型

throw new RuntimeException(“手动抛出运行时异常”);

二.使用了try catch

原理:

异常被try catch块捕获,导致事务失效。

解决方案:

在catch中抛出Spring事务支持的异常,或者你期望不回滚

三.事务方法为私有方法

原理:

Spring声明式事务基于动态代理实现,private方法不能被代理,事务不会生效。

此外,static修饰的方法属于类,不属于任何对象,也不能被代理,事务不生效。

final修饰的方法无法重写,也就不能被代理,事务也不会生效。

解决方案:

方法用public修饰,不要用static、final修饰

四.类未被Spring管理

原理:

Spring实现对象的动态代理,首先这个对象要交由Spring管理。

解决方案:

将类交由Spring管理,可添加@Service或@Component注解,或使用其他能够注册成Spring Bean的注解或方法。

五.一个方法调用本类另一个方法,事务失效

原理:

@Transactional基于AOP实现,而AOP又是基于动态代理实现,直接调用本类方法或使用this调用本类方法,均不是Spring的代理对象,无法实现动态代理,事务也就不会生效。

解决方案:

1.将两个方法合并为一个方法,用@Transactional修饰。

2.将被调用的方法放到另一个被Spring管理的类中,用实例对象调用,

3.用@Autowired在本类中注入本类实例,再用注入的实例对象调用该方法。

4.手动获取本类的代理,用代理调用该方法((TestService)AopContext.currentProxy()).myTest();

六.数据表不支持事务

原理:

Spring事务基于数据库事务实现,有些数据表本身不支持事务,如MySql的MyISAM引擎,事务自然不生效。

解决方案:

将数据表改用支持事务的引擎,如MySql的InnoDB引擎,mysql5及之后的版本默认InnnoDB。

七.Spring事务传播级别设置为不支持事务

原理:

@Transactional(propagation = Propagation.NOT_SUPPORTED) 不支持事务,若存在事务则挂起

@Transactional(propagation = Propagation.NEVER) 不使用事务,若存在事务则抛异常

解决方案:

使用Spring默认的传播级别(PROPAGATION_REQUIRED),或其他支持事务的传播级别。

八.未开启事务

解决方案:

@EnableTransactionManagement开启事务,Spring boot已自动装配,无需显示使用此注解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值