失效场景汇总
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,即不支持事务
网友评论