在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);

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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在项目配置 MySQL 事务Spring 事务的方法如下: 1. MySQL 事务配置 对于 MySQL 事务,需要在代码使用 JDBC API 来控制事务的开始、提交和回滚等操作。具体步骤如下: - 获取数据库连接:使用 DriverManager 或 DataSource 获取数据库连接。 - 开启事务:调用 Connection 对象的 setAutoCommit(false) 方法,将自动提交设置为 false,即开启事务。 - 执行数据库操作:在事务执行一组数据库操作,可以使用 PreparedStatement 或 Statement 对象来执行 SQL 语句。 - 提交事务或回滚事务:如果所有的数据库操作都执行成功,调用 Connection 对象的 commit() 方法提交事务;如果任何一个数据库操作失败,调用 Connection 对象的 rollback() 方法回滚事务。 - 关闭数据库连接:无论事务执行成功或失败,都需要关闭数据库连接。 2. Spring 事务配置 对于 Spring 事务,可以使用声明式事务或编程式事务来实现事务的控制。具体步骤如下: - 声明式事务配置:在 Spring 配置文件配置事务管理器(TransactionManager)和事务通知(TransactionAdvice),并在需要控制事务的方法上添加事务注解(@Transactional)。 - 编程式事务配置:在代码使用 TransactionTemplate 或 PlatformTransactionManager 等 Spring 提供的事务 API 来手动控制事务的开始、提交和回滚等操作。 以上是 MySQL 事务Spring 事务的基本配置方法,具体实现方式还要根据实际的业务需求和技术栈来进行选择和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值