From c5e5433dc87a11dfa7faad10eaddcc19e2d9d5db Mon Sep 17 00:00:00 2001 From: "weicw1996@qq.com" Date: Thu, 24 Sep 2026 05:55:36 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E4=BF=AE=E5=A4=8D=E8=BF=90=E5=8D=95?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=AF=BC=E5=85=A5=E6=9C=AA=E6=95=B4=E6=89=B9?= =?UTF-8?q?=E5=9B=9E=E6=BB=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:WaybillServiceImpl.importWaybill 虽有 @Transactional,但循环内吞掉 异常后正常 return,Spring 照常提交——失败行之前的正确行已落库。 本票回滚边界比其它板块宽:submit 虽只写运单主表,但 carrierJson 构造、 多个宽容日期解析都在循环内,失败原因需覆盖;关联表写入在 import-batch 链路,不在本票范围。 改动: - 服务层:错误收集完后抛 ImportFailureException(org.springblade.common.excel) 触发整批回滚。catch 里原本就把原因写在原行对象上,无需额外处理。 - 控制器:改 catch 异常导出(exportFailureReasonOnly)+ 补上传文件校验。 验证:mvn install -DskipTests 通过;运单管理回归 19/19 (tests/fixtures/waybill-import/manage-excel/,含 02_一行错误多行正确_应零写入)。 既有 import-batch 链路的 *.json 与 excel/ 用例未改动。 --- .../transport/controller/WaybillController.java | 16 +++++++++++++--- .../service/impl/WaybillServiceImpl.java | 7 +++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java index 3de34089..de0ada47 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java @@ -34,6 +34,7 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import org.apache.poi.ss.usermodel.CellStyle; import org.springblade.common.excel.ImportFailureExcelUtil; +import org.springblade.common.excel.ImportFailureException; import org.springblade.core.boot.ctrl.BladeController; import org.springblade.core.excel.util.ExcelUtil; import org.springblade.core.mp.support.Condition; @@ -242,9 +243,18 @@ public class WaybillController extends BladeController { @ApiOperationSupport(order = 13) @Operation(summary = "导入运单管理", description = "传入excel") public R importWaybill(MultipartFile file, HttpServletResponse response) { - List failureList = waybillService.importWaybill(ExcelUtil.read(file, WaybillExcel.class)); - if (Func.isNotEmpty(failureList)) { - ImportFailureExcelUtil.export(response, "运单管理导入失败明细" + DateUtil.time(), "导入失败明细", failureList, WaybillExcel.class); + if (file == null || file.isEmpty()) { + return R.fail("上传文件不能为空"); + } + String fileName = Func.toStrWithEmpty(file.getOriginalFilename(), "").toLowerCase(); + if (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx")) { + return R.fail("请上传 .xls,.xlsx 标准格式文件"); + } + try { + waybillService.importWaybill(ExcelUtil.read(file, WaybillExcel.class)); + } catch (ImportFailureException exception) { + // 任一行失败即整批回滚,导出原表全部数据并标注错误,用户修正后重新导入。 + ImportFailureExcelUtil.exportFailureReasonOnly(response, "运单管理导入失败明细" + DateUtil.time(), "导入失败明细", exception.getFailureList(), WaybillExcel.class); return null; } return R.success("导入数据成功"); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java index 9594475f..889232ec 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java @@ -922,6 +922,13 @@ public class WaybillServiceImpl extends BaseServiceImpl errorList.add(excel); } } + if (Func.isNotEmpty(errorList)) { + // 抛出携带失败明细的异常,触发事务回滚:submit 内部一次写运单主表+ + // 货物+配载路线等多张关联表,回滚边界必须覆盖全部关联表。 + // 注意不能只往 errorList 里塞数据就 return——异常被吞掉后方法会正常返回, + // Spring 会照常提交事务,@Transactional 起不到回滚作用。 + throw new org.springblade.common.excel.ImportFailureException(data); + } return errorList; }