在for循环中Spring事务单个提交问题

项目场景:

定时任务处理已经逾期的订单,在for循环里面对每个订单处理后单独事务提交,不影响整体事务

问题描述:

定时任务执行时发现并未实现在循环时处理完一个就提交,单独的事务未生效。 定时任务直接调用的外层service类大致的代码:
@Transactional(rollbackFor = Exception.class)
    public void overdueRepayProcess() {
          
   
        List<BsiLoanOrder> forbidList = new ArrayList<>();// 逾期订单列表
        // 省略查询逾期订单的逻辑
        /* 逾期订单处理 */
        if (CollectionUtil.isEmpty(forbidList)) {
          
   
            return;
        }
        int num = 0;
        for (BsiLoanOrder order : forbidList) {
          
   
            /* 使用锁机制,处理订单时不能让用户进行操作 */
            boolean lockFlag = LockDoorUtil.setKey(LOCK_KEY_PREFIX + order.getId());
            try {
          
   
                if(!lockFlag) {
          
   
                    continue;
                }
                // service类内部方法,逾期订单处理
                this.forbidListProcess(order);
                num++;
            } catch (Exception e) {
          
   
                log.error("【逾期订单" + order.getId() + "处理】报错", e);
            } finally {
          
   
                LockDoorUtil.delKey(LOCK_KEY_PREFIX + order.getId(), lockFlag);
            }
        }
    }
	
	 /**
     * 逾期订单处理(单独事务)
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void forbidListProcess(BsiLoanOrder order) {
          
   
        // 省略内部逻辑
    }

原因分析:

用spring声明式事务,最外层方法直接调用该类的内部方法是不会走到代理类的,也就是不会走到切面,所以forbidListProcess方法上的@Transactional会失效

解决方案:

把forbidListProcess方法写在新的service类里即可。
/**
 * 逾期订单处理服务类
 */
@Service
public class LoanOverdueProcessService {
          
   

	/**
     * 逾期订单处理(单独事务)
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void forbidListProcess(BsiLoanOrder order) {
          
   
        // 省略内部逻辑
    }
}

外层service类里面

// service类内部方法,逾期订单处理
this.forbidListProcess(order);

改为

// 单独事务不影响循环
loanOverdueProcessService.forbidListProcess(order);

再次运行定时任务,循环一个就提交一次事务,问题解决

经验分享 程序员 微信小程序 职场和发展