Spring事务失效的原因
Spring事务失效:有事务注解的方法,出现了异常,却没有回滚数据。
一个事务的方法,出现了异常,没有正确地回滚数据,我们应该怎么排除错误?
我们以这句话为出发点,开始记下面的知识。
记忆口诀:
哭泣着,抓住错误的对象。
哭 ,泣 ,抓住 ,错误的 ,对象
数据库,事务管理器,抓住异常,错误的传播类型,代理对象
一、数据库
MySQL的数据库引擎,InnoDB支持事务,MyISAM不支持事务。
二、事务管理器
配置事务管理器
注解方式:@EnableTransactionManagement
配置方式:
<!--1 创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property><!--注入数据源-->
</bean>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
三、抓住异常
1、在事务方法内,使用了try...catch捕获异常,而catch里没有throw 要回滚的异常,事务不会回滚。
@Transactional(rollbackFor = RuntimeException.class)
Throwable | ||||
Exception | Error | |||
SQLException | RuntimeException | VirtualMachineError | ||
NestedRuntimeException | NullPointerException | StackOverflowError | OutOfMemoryError | |
DataAccessException | ||||
NonTransientDataAccessException | ||||
DataIntegrityViolationException |
2、rollbackFor 默认对RuntimeException 和Error 以及它们的子类,做回滚。
四、错误的传播类型
传播类型默认是REQUIRED。
比如:在方法上加“@Transactional(propagation = Propagation.SUPPORTS)”,就相当于啥也没加。
参见:嘘!看紫色的光头强,送给猩猩一匹紫色的布,并且决不收它的钱钱。
五、代理对象
Spring事务是通过AOP,生成代理对象的代理方法,来实现的。
建议在实现类的方法上加 @Transactional 注解,不要在接口里加注解。
5.1、Transactional注解只能放在public方法上
默认配置时,@Transactional注解只能放在public方法上。放在private,protected方法上,事务无效,但不会报错。
让@Transactional在protected方法生效的配置。示例代码:gitee.com/SevenDayBabyface/jiwei
@Bean(name = "transactionAttributeSource")
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource(false);
}
class AnnotationTransactionAttributeSource 注解事务属性源
abstract class AbstractFallbackTransactionAttributeSource 抽象的备用的事务属性源
interface TransactionAttributeSource 事务属性源
Create a custom AnnotationTransactionAttributeSource, supporting public methods that carry the {@code Transactional} annotation.
@param publicMethodsOnly whether to support public methods that carry the {Transactional} annotation only, or protected/private methods as well.
创建自定义 注释事务属性源,支持带有@Transactional注解的公共方法。
参数publicMethodsOnly:是只支持public方法,还是也支持protected方法。
5.2、在类的内部,自身调用
类中直接调用本类的方法,事务失效。因为事务通过aop实现。
Spring事务,调用代理类的对象的方法,才是使用了事务。