@Transactional失效场景

2023-09-11  本文已影响0人  玖柒叁

失效场景汇总

image.png

使用@Transactional要注意以下几个问题:数据库引擎是否支持事务、Spring中是否配置开启@Transactional事务、propgation设置错误、rollbackFor设置错误、catch的时候吞了异常、在同类中的普通方法调用事务方法、事务方法不是public的。

失效场景详述

底层是否支持

数据库引擎是否支持事务

使用事务首先要确认自己选择的数据库引擎是否支持事务,如现在大部分公司选择的MySQL的innodb引擎是支持事务的

配置是否正确

Spring中是否配置开启@Transactional事务

@EnableTransactionManagement开启注解版本事务功能

propgation设置错误

propgation定义了@Transactional的边界:是否使用事务、在存在事务时如何表现
事务的传播机制如下所示:
Propagation.REQUIRED:如果当前存在事务,则使用该事务。 如果当前没有事务,则创建一个新的事务。
Propagation.REQUIRES_NEW:创建一个新的事务,如果当前有事务,暂停当前的事务。
Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行
Propagation.MANDATORY:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常
Propagation.NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务,暂停当前的事务。
Propagation.NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常。
Propagation.NESTED:如果当前存在事务,则创建一个嵌套事务来运行,如果当前没有事务,行为等同于PROPAGATION_REQUIRED

rollbackFor设置错误

定义了在抛出什么样的异常时事务会进行回滚。Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务。

代码是不是合理

catch的时候吞了异常

如果想要spring事务能够正常回滚,必须抛出它能够处理的异常。如果没有抛异常,则spring认为程序是正常的

在同类中的普通方法调用事务方法

@Transactional事务主要是利用springAOP生产代理对象,然后用代理对象来进行事务的提交,在使用JDK的动态代理时,代理类在处理完增强逻辑后通过反射调用了目标类的原始方法,之后便是直接在该原始方法里面执行逻辑,如果代理类最初调用的是一个普通的方法,那么调用该方法之前并没有进行增强,而后所有的逻辑都在目标类中执行,因此即使此时在目标类中调用了事务方法其实也并没有进行代理。因此事务会失效。

事务方法不是public的

在生成代理类时,如果注解的方法不是public的话,会导致事务失效,原因是在AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法中有个判断,如果目标方法不是public,则TransactionAttribute返回null,即不支持事务

参考文章

事务失效的6种场景
事务失效的12种场景

上一篇 下一篇

猜你喜欢

热点阅读