Spring事务失效原因及解决方法

spring 提供事务功能需要依赖于数据库的事务支持。而数据库层的事务提交和回滚是通过bin log 或者 redo log 实现的。大部分情况下我们使用基于 @Transactional 注解的声明式事务。声明式事务本质是通过 AOP 功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

对于Spring事务来说,在以下9种情况下会出现事务失效的情况。

1、数据库本身不支持事务

以 MySQL 为例,MyISAM 引擎是不支持事务操作的,InnoDB ,要支持事务都会使用 InnoDB引擎。

解决方法:使用支持事务的数据库引擎。

2、事务没有被Spring管理

没有被@service、@component等注解修饰,这个类没有被Spring加载成一个bean,此时这个类没有被Spring管理了,Spring事务就失效了。

3、同一类中的自身方法调用

因为spring声明式事物是基于AOP实现的,是使用动态代理来达到事物管理的目的,当前类调用的方法上面加@Transactional 这个是没有任何作用的,因为调用这个方法的是this,没有经过 Spring 的代理类。

解决方法:1)在声明一个service,将内部调用改为外部调用。

 

2) 使用编程式事务

4、方法不是Public

Spring官方文档中有明确的说明,@Transactional 只有修饰public方法时才会生效,修饰protected、private或者包内可见的方法均不会生效。

解决方法:@Transactional 修饰public方法即可,或者@Transactional 修饰类,需要事务生效的方法都为public。

5、事物传播性问题

Spring 事务的传播行为定义如下:

  • PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
  • PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行
  • PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
  • PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
  • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按 REQUIRED 属性执行

当传播行为设置了PROPAGATION_NOT_SUPPORTED,PROPAGATION_NEVER,PROPAGATION_SUPPORTS这三种时,就有可能存在事物不生效。

解决方法:尽量避免使用上面三种传播行为。

6、数据源未配置事务管理器

如上面所示,当前数据源若没有配置事务管理器,那么事务是不会生效的。

解决方法:有配置事务管理器。

7、使用cglib代理

要注意的是单纯使用cglib代理是不会出现事务失效的情况,只有当接口层使用声明式事务同时使用了cglib代理才会出现事务失效的情况。如下图为接口层使用声明式事务示例。

解决方法:cglib代理和接口层声明式事务二者不同时使用。

8、rollbackFor异常指定错误

例如rollbaclFor指定的是DataFormatException,但程序没有抛DataFormatException,因此事务不会回滚。若没有指定回滚异常,默认的回滚异常是RuntimeException ,如果出现其他异常那么就不会回滚事物。

解决方法:明确需要回滚的异常,正确设置rollbackFor的异常class。

9、异常被catch住了

代码中手动catch了异常,然后又未抛出来,此时事务就不生效了。

解决方法:要么不catch需要回滚的异常,要么catch之后再抛出。

  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值