Browse Source

物料属性失败不影响整体事务

master
han\hanst 2 weeks ago
parent
commit
7b03fd37a8
  1. 59
      src/main/java/com/gaotao/modules/warehouse/service/impl/IfsInventoryInitServiceImpl.java

59
src/main/java/com/gaotao/modules/warehouse/service/impl/IfsInventoryInitServiceImpl.java

@ -758,8 +758,8 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService {
* <p><b>注意:</b></p>
* <ul>
* <li>inventory_stock_ifs表:只插入不更新,记录已存在则报错</li>
* <li>part_attribute表:记录已存在则跳过,不报错;插入异常则整批失败</li>
* <li>任一行校验或写入失败:一行都不保留,已写入的数据随事务回滚</li>
* <li>part_attribute表:已存在则跳过;写入失败只记日志,不回滚、不返回给前端</li>
* <li>库存行校验或写入失败:一行都不保留,已写入的数据随事务回滚</li>
* </ul>
*
* @param file Excel文件
@ -953,33 +953,41 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService {
int partAttributeSkipped = 0;
int partAttributeSaved = 0;
int partAttributeFailed = 0;
for (Map<String, Object> rowData : successList) {
int rowNumber = (int) rowData.get("rowNumber");
try {
// 1. 插入inventory_stock_ifs表(已存在则抛错)
// 库存写入失败仍整批回滚;料件属性不放在这个 try 里,避免主键冲突中断导入
insertOrUpdateIfsInventory(rowData);
} catch (Exception e) {
log.error("第{}行数据插入失败: {}", rowNumber, e.getMessage(), e);
errorMessages.add("第" + rowNumber + "行: 数据库插入失败 - " + e.getMessage());
// 前面的行已在同一事务里写入;正常返回会提交,必须显式标记回滚才能一行都不留
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
log.warn("=== IFS库存Excel写入失败,已标记整批回滚 === 失败行: {}", rowNumber);
return buildImportAbortResult(errorMessages);
}
// 2. 插入part_attribute表(已存在则跳过,插入异常向上抛出)
PartAttribute partAttribute = (PartAttribute) rowData.get("part_attribute");
if (partAttribute != null) {
PartAttribute partAttribute = (PartAttribute) rowData.get("part_attribute");
if (partAttribute != null) {
try {
boolean saved = insertPartAttributeIfNotExists(partAttribute);
if (saved) {
partAttributeSaved++;
} else {
partAttributeSkipped++;
}
} catch (Exception e) {
// 属性失败不能进入错误结果:前端会据此提示“未写入任何数据”,库存事务也不能因此回滚
partAttributeFailed++;
log.error("第{}行料件属性写入失败,已忽略,不影响库存导入: site={}, partNo={}, 原因: {}",
rowNumber, partAttribute.getSite(), partAttribute.getPartNo(), e.getMessage(), e);
}
} catch (Exception e) {
log.error("第{}行数据插入失败: {}", rowNumber, e.getMessage(), e);
errorMessages.add("第" + rowNumber + "行: 数据库插入失败 - " + e.getMessage());
// 前面的行已在同一事务里写入;正常返回会提交,必须显式标记回滚才能一行都不留
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
log.warn("=== IFS库存Excel写入失败,已标记整批回滚 === 失败行: {}", rowNumber);
return buildImportAbortResult(errorMessages);
}
}
log.info("=== part_attribute表处理统计 === 新增: {}, 跳过: {}", partAttributeSaved, partAttributeSkipped);
log.info("=== part_attribute表处理统计 === 新增: {}, 跳过: {}, 失败已忽略: {}",
partAttributeSaved, partAttributeSkipped, partAttributeFailed);
log.info("=== IFS库存Excel导入完成 === 成功: {}, 失败: 0", successList.size());
Map<String, Object> result = new HashMap<>();
@ -1037,8 +1045,8 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService {
}
/**
* 插入part_attribute记录(如果不存在)
* 已存在视为跳过,不报错;插入失败必须抛出,否则库存行会在属性写入失败时被单独提交。
* 插入part_attribute记录(如果不存在)。
* 已存在则跳过。插入失败先回滚到保存点再抛出,由调用方记日志后继续,不能把库存导入事务标成回滚。
*
* @param partAttribute 料件属性对象
* @return true=成功插入,false=已存在跳过
@ -1053,7 +1061,24 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService {
return false;
}
partAttributeMapper.insert(partAttribute);
// SQL Server 主键冲突只中止当前语句,但连接上的事务可能无法再提交。
// 保存点把失败限制在这次属性插入,回滚后库存导入仍可继续。
Object savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
try {
partAttributeMapper.insert(partAttribute);
} catch (Exception e) {
try {
TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
} catch (Exception rollbackEx) {
log.error("料件属性保存点回滚失败: site={}, partNo={}",
partAttribute.getSite(), partAttribute.getPartNo(), rollbackEx);
}
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new RuntimeException(e);
}
TransactionAspectSupport.currentTransactionStatus().releaseSavepoint(savepoint);
log.debug("料件属性新增成功: site={}, partNo={}",
partAttribute.getSite(), partAttribute.getPartNo());
return true;

Loading…
Cancel
Save