From 0b0655174a66fe84bdc7a10abca08d52e2ebb65c Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Fri, 6 Feb 2026 10:06:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=91=98=E5=B7=A5?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E5=BC=82=E6=AD=A5=E6=96=B9=E6=B3=95=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 问题 - importEmployeeAsync方法在返回CompletableFuture之前同步调用了doImport() - 方法上有@Transactional注解,会导致事务管理问题 - 不是真正的异步执行 ## 解决方案 - 移除importEmployeeAsync方法上的@Transactional注解 - 使用CompletableFuture.supplyAsync()在importExecutor线程池中异步执行doImport - 将@Transactional注解移到doImport方法上 - 注入importExecutor线程池 ## 技术细节 - @Async注解会将方法提交到线程池执行 - CompletableFuture.supplyAsync()确保doImport在独立线程中执行 - 事务在doImport方法中管理,避免异步方法事务问题 Co-Authored-By: Claude Sonnet 4.5 --- .../service/impl/CcdiEmployeeServiceImpl.java | 57 ++++++++++++------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiEmployeeServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiEmployeeServiceImpl.java index bbd28ae..092fed5 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiEmployeeServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiEmployeeServiceImpl.java @@ -25,6 +25,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -43,6 +45,9 @@ public class CcdiEmployeeServiceImpl implements ICcdiEmployeeService { @Resource private RedisTemplate redisTemplate; + @Resource + private Executor importExecutor; + /** * 查询员工列表 * @@ -235,7 +240,6 @@ public class CcdiEmployeeServiceImpl implements ICcdiEmployeeService { */ @Override @Async("importExecutor") - @Transactional public CompletableFuture importEmployeeAsync(List excelList, Boolean isUpdateSupport) { String taskId = UUID.randomUUID().toString(); long startTime = System.currentTimeMillis(); @@ -255,30 +259,40 @@ public class CcdiEmployeeServiceImpl implements ICcdiEmployeeService { redisTemplate.opsForHash().putAll(statusKey, statusData); redisTemplate.expire(statusKey, 7, TimeUnit.DAYS); - try { - // 执行导入 - ImportResult result = doImport(excelList, isUpdateSupport, taskId); + // 使用CompletableFuture.supplyAsync在独立的executor中异步执行doImport + return CompletableFuture.supplyAsync(() -> { + try { + // 在独立线程中执行导入 + ImportResult result = doImport(excelList, isUpdateSupport, taskId); - // 更新最终状态 - String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; - updateImportStatus(taskId, finalStatus, result, startTime); + // 更新最终状态 + String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS"; + updateImportStatus(taskId, finalStatus, result, startTime); - } catch (Exception e) { - // 处理异常 - Map errorData = new HashMap<>(); - errorData.put("status", "FAILED"); - errorData.put("message", "导入失败: " + e.getMessage()); - errorData.put("endTime", System.currentTimeMillis()); - redisTemplate.opsForHash().putAll(statusKey, errorData); - } + // 构建返回结果 + ImportResultVO resultVO = new ImportResultVO(); + resultVO.setTaskId(taskId); + resultVO.setStatus(finalStatus); + resultVO.setMessage("导入完成"); - // 立即返回结果,不等待后台任务完成 - ImportResultVO result = new ImportResultVO(); - result.setTaskId(taskId); - result.setStatus("PROCESSING"); - result.setMessage("导入任务已提交,正在后台处理"); + return resultVO; - return CompletableFuture.completedFuture(result); + } catch (Exception e) { + // 处理异常 + Map errorData = new HashMap<>(); + errorData.put("status", "FAILED"); + errorData.put("message", "导入失败: " + e.getMessage()); + errorData.put("endTime", System.currentTimeMillis()); + redisTemplate.opsForHash().putAll(statusKey, errorData); + + ImportResultVO resultVO = new ImportResultVO(); + resultVO.setTaskId(taskId); + resultVO.setStatus("FAILED"); + resultVO.setMessage("导入失败: " + e.getMessage()); + + return resultVO; + } + }, importExecutor); } /** @@ -426,6 +440,7 @@ public class CcdiEmployeeServiceImpl implements ICcdiEmployeeService { /** * 执行导入逻辑 */ + @Transactional private ImportResult doImport(List excelList, Boolean isUpdateSupport, String taskId) { List newRecords = new ArrayList<>(); List updateRecords = new ArrayList<>();