SpringBoot中实现单条关联数据删除失败仅回滚当前记录
解决方案
核心思路是为每条待清理的卡片单独创建独立事务,这样某条处理失败时,仅回滚该条对应的事务,不影响其他卡片的清理流程。具体调整如下:
关键修改点
- 移除方法上的
@Transactional注解,避免外层大事务包裹所有操作 - 将单条卡片的清理逻辑放入
TransactionTemplate中,且每条卡片对应一个独立事务 - 为单条卡片的处理添加异常捕获,出错时记录日志并继续处理下一条
调整后的代码
private void purgeCards(List<CardEntity> cardsTobePurge) { List<Long> nextCardsNumberToUpdate = getNextCardsWhichWillNotBePurge(cardsTobePurge); TransactionTemplate transTemplate = new TransactionTemplate(transactionManager); // 设置为REQUIRES_NEW,确保每条卡片的事务独立于其他操作 transTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); for (CardEntity cardTobePurge : cardsTobePurge) { try { transTemplate.execute(status -> { Long nextCardNumberOfCurrent = cardTobePurge.getNextCard(); if (nextCardsNumberToUpdate.contains(nextCardNumberOfCurrent)) { CardEntity cardToUnlink = cardRepository.findByCardNumber(nextCardNumberOfCurrent); unLink(cardToUnlink); } log.info(BATCH_TITLE + " Removing card Number : " + cardTobePurge.getCardNumber() + " with Id : " + cardTobePurge.getId()); // 关联数据删除 List<CardHistoryEntity> historyEntitiesOfThisCard = cardHistoryRepository.findByCard(cardTobePurge); List<LogCreationCardEntity> logCreationEntitiesForThisCard = logCreationCardRepository .findByCardNumber(cardTobePurge.getCardNumber()); List<LogCustomerMergeEntity> logCustomerMergeEntitiesForThisCard = logCustomerMergeRepository .findByCard(cardTobePurge); cardHistoryRepository.deleteAll(historyEntitiesOfThisCard); logCreationCardRepository.deleteAll(logCreationEntitiesForThisCard); logCustomerMergeRepository.deleteAll(logCustomerMergeEntitiesForThisCard); cardRepository.delete(cardTobePurge); return Boolean.TRUE; }); } catch (Exception e) { // 记录错误日志,当前卡片事务自动回滚,不影响后续处理 log.error(BATCH_TITLE + " Failed to remove card Number : " + cardTobePurge.getCardNumber() + " with Id : " + cardTobePurge.getId(), e); } } }
逻辑说明
- 独立事务控制:通过
TransactionTemplate的PROPAGATION_REQUIRES_NEW传播行为,确保每条卡片的清理操作都在全新事务中执行,与其他卡片的事务完全隔离。 - 异常隔离:循环中为每条卡片的事务执行添加
try-catch,当某条处理抛出异常时,该事务自动回滚,捕获异常并记录日志后,循环继续执行下一条卡片的清理。 - 保留原有业务逻辑:完整保留了你原本的关联数据处理、日志删除等逻辑,仅调整事务的作用范围以实现需求。
内容的提问来源于stack exchange,提问作者Amine Choukri
相关产品推荐
相关产品推荐

