Spring声明式事务的特性及易出错的情况

 

说明:Spring的声明式事务,默认情况下只对RuntimeException非受检异常及其子类或者 Error异常及其子类才会执行回滚,而Exception受检异常是不回滚的。

分析: 大多数情况下,使用者要求对事务的回滚,不仅仅局限于运行时异常(即非受检异常) 才需要回滚,而是出现异常都进行回滚。

正例: 在开启事务时指定对Exception受检异常回滚,只要是Exception异常或者其子类异常都会回滚。

     @Transactional(rollbackFor = {Exception.class})

     public class CustomerServiceImpl implements CustomerService

 

说明:Spring的声明式事务,通过代理代理,采用切面的方式来透明的增加事务操作,如果直接在目标 对象内部调用方法,没有切面包装的,就不会通过事务调用。

 

分析:当获取有开启事务的Service对象时,Spring注入进来的bean并不是原实现类的对象,而是通过 继承原对象动态生成一个代理java类,并创建这个代理对象,然后依赖注入到使用者中,当使用 者调用时Service方法时,会先经过代理包装的处理逻辑,然后才调用原对象的实际逻辑。

 分析: 单独调用saveCustomerBasicInfo方法或者saveCustomerWorkInfo方法,是有事务切入的, 但是this.saveCustomerWorkInfo(null, urUser);方法是没经过事务切入的。

 

 说明:当Service调用多个Service的方法时,如果是使用同一个事务,即使调用者有try-catch捕捉了异常, 也会导致事务的回滚。

 

 

说明:mysql默认的隔离级别是Repeatable read 是保证同一事务内可重复读。导致在同一事物时, 首次进行查询后,就好对该表生成快照,导致后续每次读取同一个表的数据时都相同。 即使有存在有已提交事务的数据,也不会被读取出来。

 说明:当在有开启事务的ServiceA的方法中,调用ServiceB的方法时,如果ServiceB的方法是独立的, 不受外部事务的影响,则需要给ServiceB的方法单独开启新的事务。

使用方案:

 1、直接在ServiceB的方法上增加事务注解,指定事务传播方式:

       @Transactional(rollbackFor = Exception.class, propagation=Propagation.REQUIRES_NEW)

       public List<XdBankInfo> findRepetition(XdBankInfo xdBankInfo) {

             ……

       }

 2、包装在事务执行器里TransactionExecutor对象

      transactionExecutor.execUseNewTrans(ts -> {

          ….

      });

附加:Spring的声明式事务在项目里非常常用,但是很多开发人员并没去了解其中的原理,事务是否生效也不知情,导致生产出现了bug后才来细查原因。最好的方式,就是做单元测试,模拟异常看数据回滚情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奕辰杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值