🐛 修复常用线路导入未整批回滚
问题:CommonRouteServiceImpl.importCommonRoute 循环内吞掉异常后正常 return, 方法正常返回导致 Spring 照常提交事务。方法虽有 @Transactional(rollbackFor = Exception.class),但异常被吞后注解救不了——失败行之前的正确行已经落库。 改动: - 服务层:错误收集完毕后若 failureList 非空,抛 ImportFailureException (org.springblade.common.excel)触发整批回滚。catch 里原本就把原因 写在原行对象上,失败明细原因不丢,无需额外处理。 - 控制器:改为 catch 异常 → 取 failureList 导出(exportFailureReasonOnly) → return null,并补上传文件校验,对齐 PortTerminalController 写法。 验证: - mvn install -DskipTests 全量编译通过。 - 常用线路回归 29/29 通过(新增 tests/fixtures/common-route/, scripts/api-common-route-import-test.sh),含 02_一行错误多行正确_应零写入、 07_与库中线路重名(基线行不受回滚影响)。 - 港口码头 45/45、常用货物 25/25 基线回归通过,确认无连带影响。
This commit is contained in:
+14
-6
@@ -38,6 +38,7 @@ import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.utils.DateUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.common.excel.ImportFailureExcelUtil;
|
||||
import org.springblade.common.excel.ImportFailureException;
|
||||
import org.springblade.transport.excel.CommonRouteExportExcel;
|
||||
import org.springblade.transport.excel.CommonRouteImportExcel;
|
||||
import org.springblade.transport.pojo.entity.CommonRoute;
|
||||
@@ -109,15 +110,22 @@ public class CommonRouteController extends BladeController {
|
||||
@ApiOperationSupport(order = 6)
|
||||
@Operation(summary = "导入常用线路", description = "传入excel")
|
||||
public R importCommonRoute(MultipartFile file, HttpServletResponse response) {
|
||||
List<CommonRouteImportExcel> failureList = commonRouteService.importCommonRoute(
|
||||
ExcelUtil.read(file, CommonRouteImportExcel.class)
|
||||
);
|
||||
if (Func.isNotEmpty(failureList)) {
|
||||
ImportFailureExcelUtil.export(
|
||||
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 {
|
||||
commonRouteService.importCommonRoute(ExcelUtil.read(file, CommonRouteImportExcel.class));
|
||||
} catch (ImportFailureException exception) {
|
||||
// 任一行失败即整批回滚,导出原表全部数据并标注错误,用户修正后重新导入。
|
||||
ImportFailureExcelUtil.exportFailureReasonOnly(
|
||||
response,
|
||||
"常用线路导入失败明细" + DateUtil.time(),
|
||||
"导入失败明细",
|
||||
failureList,
|
||||
exception.getFailureList(),
|
||||
CommonRouteImportExcel.class
|
||||
);
|
||||
return null;
|
||||
|
||||
+10
@@ -25,6 +25,7 @@ package org.springblade.transport.service.impl;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springblade.common.excel.ImportFailureException;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.mp.base.BaseServiceImpl;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
@@ -130,6 +131,10 @@ public class CommonRouteServiceImpl extends BaseServiceImpl<CommonRouteMapper, C
|
||||
if (Func.isEmpty(data)) {
|
||||
throw new ServiceException("导入数据不能为空");
|
||||
}
|
||||
// 全量校验:任何一行失败都整批回滚,因此先收集所有错误再统一抛出。
|
||||
// 注意:本方法虽已标注 @Transactional,但循环内把异常吞掉后正常 return,
|
||||
// Spring 会认为一切成功并提交事务——注解救不了被吞掉的异常。
|
||||
// 必须把错误明细收集完后抛异常,回滚才会真正发生。
|
||||
List<CommonRouteImportExcel> failureList = new ArrayList<>();
|
||||
for (int index = 0; index < data.size(); index++) {
|
||||
CommonRouteImportExcel excel = data.get(index);
|
||||
@@ -142,6 +147,11 @@ public class CommonRouteServiceImpl extends BaseServiceImpl<CommonRouteMapper, C
|
||||
failureList.add(excel);
|
||||
}
|
||||
}
|
||||
if (Func.isNotEmpty(failureList)) {
|
||||
// 抛出携带失败明细的异常,触发事务回滚。
|
||||
// 明细为原表全部行(未出错行仅无错误原因),用户可对照原表修正后重新导入。
|
||||
throw new ImportFailureException(data);
|
||||
}
|
||||
return failureList;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user