记录日常使用Transactional 注解时出现的失效不回滚的问题

        写完代码又一次习惯性的在方法上加了 Transactional 注解来开启事务的处理,但是本次我突然发现 居然失效了!!!接下来说一下的事情的经过。

1. 事发现场

@Transactional(rollbackFor = Exception.class)
public void someMethod() {
    for (...) {
         try {
             xxxMapper.insert(item);
             findItemConfig(Long.parseLong(item.getBenchmarkRelId()),item.getId());
       } catch (Exception e) {
           throw new RuntimeException("Find standard item config failed: "+e.getMessage()e);
}
    }
}

2.事故描述,分析原因

        当findItemConfig方法发生异常的时候, xxxMapper.insert(item);居然正常执行,并没有发生回滚,然后我陷入了自我怀疑当中:难道之前一贯的用法时错误的?之后又手动造了几个异常,发现依然不回滚。沉思一番,快速扫描了一遍写的代码,注解正常,那就只有一个原因了。嗯......好吧,我承认在代码上有些失误。

        是因为在for循环中的缘故,在循环内部无法触发 @Transactional 注解的回滚是因为事务的控制粒度问题。通常情况下,Spring 会通过 AOP(面向切面编程)来实现 @Transactional 的功能。当一个方法被调用时,Spring 会在其周围创建一个事务边界,并在方法执行前后进行事务的开启、提交或回滚等操作。然而,在循环内部,每次迭代都会执行一次循环体代码块,这些迭代往往不会被 Spring 感知到,因此事务边界无法正确地包含多个迭代操作。解决这个问题有两个方法,声明性事务(@Transactional 注解)编程事务来实现更细粒度的事务控制。

3.解决方法

        声明性事务:

@Transactional(rollbackFor = Exception.class)
public void someMethod() {
    for (...) {
        // 循环体代码块
        doSomething();
    }
}

@Transactional(rollbackFor = Exception.class)
public void doSomething() {
    // 执行具体的操作
}

        编程事务:

    public void someMethod() {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        TransactionStatus status = transactionManager.getTransaction(def);

        try {
            for (...) {
				 // 循环体代码块
            }

            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值