库位修改以及批量导入 不能重复的校验
This commit is contained in:
@@ -99,5 +99,18 @@ public interface PcdeDetailMapper
|
||||
|
||||
String selectEncodedIdByPcodeAndWarehouse(@Param("pcode") String pcode,
|
||||
@Param("warehouseCode") String warehouseCode);
|
||||
/**
|
||||
* 新增前查重
|
||||
* 同一仓库、同一场景、同一库位编码,不允许重复
|
||||
*/
|
||||
public PcdeDetail selectByWarehouseSceneAndPcode(PcdeDetail pcdeDetail);
|
||||
|
||||
/**
|
||||
* 修改前查重(排除自己)
|
||||
*/
|
||||
public PcdeDetail selectRepeatByWarehouseSceneAndPcode(PcdeDetail pcdeDetail);
|
||||
/**
|
||||
* 批量查已存在
|
||||
*/
|
||||
List<PcdeDetail> selectExistsForImport(@Param("list") List<PcdeDetail> list);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,15 @@ public class PcdeDetailServiceImpl implements IPcdeDetailService
|
||||
*/
|
||||
@Override
|
||||
public int insertPcdeDetail(PcdeDetail pcdeDetail) {
|
||||
pcdeDetail.setWarehouseCode(pcdeDetail.getWarehouseCode().trim());
|
||||
pcdeDetail.setScene(pcdeDetail.getScene().trim());
|
||||
pcdeDetail.setPcode(pcdeDetail.getPcode().trim());
|
||||
// 查重:同一仓库、同一场景、同一库位编码
|
||||
PcdeDetail exist = pcdeDetailMapper.selectByWarehouseSceneAndPcode(pcdeDetail);
|
||||
if (exist != null)
|
||||
{
|
||||
throw new RuntimeException("当前仓库、当前场景下已存在该库位编码,请勿重复新增");
|
||||
}
|
||||
// 原始 locationCode
|
||||
String locationCode = pcdeDetail.getPcode();
|
||||
|
||||
@@ -86,6 +95,16 @@ public class PcdeDetailServiceImpl implements IPcdeDetailService
|
||||
@Override
|
||||
public int updatePcdeDetail(PcdeDetail pcdeDetail)
|
||||
{
|
||||
pcdeDetail.setWarehouseCode(pcdeDetail.getWarehouseCode().trim());
|
||||
pcdeDetail.setScene(pcdeDetail.getScene().trim());
|
||||
pcdeDetail.setPcode(pcdeDetail.getPcode().trim());
|
||||
|
||||
// 查重:排除自己
|
||||
PcdeDetail exist = pcdeDetailMapper.selectRepeatByWarehouseSceneAndPcode(pcdeDetail);
|
||||
if (exist != null)
|
||||
{
|
||||
throw new RuntimeException("当前仓库、当前场景下已存在该库位编码,请勿重复修改");
|
||||
}
|
||||
return pcdeDetailMapper.updatePcdeDetail(pcdeDetail);
|
||||
}
|
||||
|
||||
@@ -155,49 +174,96 @@ public class PcdeDetailServiceImpl implements IPcdeDetailService
|
||||
|
||||
final Date now = DateUtils.getNowDate();
|
||||
|
||||
// 1) 清洗 + 本地生成 encodedId(逐字符→Unicode→HEX大写→拼接)
|
||||
// 1. 清洗数据
|
||||
List<PcdeDetail> cleaned = new ArrayList<>(pcdeList.size());
|
||||
|
||||
// 文件内去重:同一仓库+同一场景+同一库位编码
|
||||
Set<String> importKeySet = new HashSet<>();
|
||||
int innerRepeatCount = 0;
|
||||
|
||||
for (PcdeDetail d : pcdeList) {
|
||||
if (d == null) continue;
|
||||
String p = d.getPcode() == null ? null : d.getPcode().trim();
|
||||
if (StringUtils.isEmpty(p)) {
|
||||
// 跳过空 pcode
|
||||
if (d == null) {
|
||||
continue;
|
||||
}
|
||||
d.setPcode(p);
|
||||
d.setEncodedId(toHexStringFromPcode(p));
|
||||
|
||||
// 审计字段(与你实体保持一致:createdBy/createdAt/updatedBy/updatedAt)
|
||||
String warehouseCode = d.getWarehouseCode() == null ? null : d.getWarehouseCode().trim();
|
||||
String scene = d.getScene() == null ? null : d.getScene().trim();
|
||||
String pcode = d.getPcode() == null ? null : d.getPcode().trim();
|
||||
|
||||
if (StringUtils.isEmpty(warehouseCode) || StringUtils.isEmpty(scene) || StringUtils.isEmpty(pcode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String repeatKey = warehouseCode + "_" + scene + "_" + pcode;
|
||||
if (importKeySet.contains(repeatKey)) {
|
||||
innerRepeatCount++;
|
||||
continue;
|
||||
}
|
||||
importKeySet.add(repeatKey);
|
||||
|
||||
d.setWarehouseCode(warehouseCode);
|
||||
d.setScene(scene);
|
||||
d.setPcode(pcode);
|
||||
d.setEncodedId(toHexStringFromPcode(pcode));
|
||||
|
||||
d.setCreatedBy(operName);
|
||||
d.setCreatedAt(now);
|
||||
d.setUpdatedBy(operName);
|
||||
d.setUpdatedAt(now);
|
||||
|
||||
// 业务兜底
|
||||
if (d.getIsDelete() == null) d.setIsDelete("0");
|
||||
if (d.getIsDelete() == null) {
|
||||
d.setIsDelete("0");
|
||||
}
|
||||
|
||||
cleaned.add(d);
|
||||
}
|
||||
|
||||
if (cleaned.isEmpty()) {
|
||||
throw new ServiceException("有效的库位编号为空,请检查导入文件!");
|
||||
throw new ServiceException("有效的导入数据为空,请检查导入文件!");
|
||||
}
|
||||
|
||||
// 2) 批量写库(分片,避免 SQL 过大;配合 uk_pcode + INSERT IGNORE 实现幂等忽略)
|
||||
// 2. 批量查数据库已存在数据
|
||||
List<PcdeDetail> existList = pcdeDetailMapper.selectExistsForImport(cleaned);
|
||||
|
||||
Set<String> dbExistKeySet = new HashSet<>();
|
||||
if (!CollectionUtils.isEmpty(existList)) {
|
||||
for (PcdeDetail item : existList) {
|
||||
String key = item.getWarehouseCode() + "_" + item.getScene() + "_" + item.getPcode();
|
||||
dbExistKeySet.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 过滤数据库中已存在的数据
|
||||
List<PcdeDetail> needInsertList = new ArrayList<>();
|
||||
int dbRepeatCount = 0;
|
||||
|
||||
for (PcdeDetail d : cleaned) {
|
||||
String key = d.getWarehouseCode() + "_" + d.getScene() + "_" + d.getPcode();
|
||||
if (dbExistKeySet.contains(key)) {
|
||||
dbRepeatCount++;
|
||||
continue;
|
||||
}
|
||||
needInsertList.add(d);
|
||||
}
|
||||
|
||||
if (needInsertList.isEmpty()) {
|
||||
return String.format("导入完成:共读取 %d 条,文件内重复 %d 条,数据库已存在 %d 条,本次成功导入 0 条。",
|
||||
pcdeList.size(), innerRepeatCount, dbRepeatCount);
|
||||
}
|
||||
|
||||
// 4. 分批插入
|
||||
final int batchSize = 1000;
|
||||
int totalTried = cleaned.size();
|
||||
int totalInserted = 0;
|
||||
|
||||
for (int i = 0; i < cleaned.size(); i += batchSize) {
|
||||
int end = Math.min(i + batchSize, cleaned.size());
|
||||
List<PcdeDetail> slice = cleaned.subList(i, end);
|
||||
for (int i = 0; i < needInsertList.size(); i += batchSize) {
|
||||
int end = Math.min(i + batchSize, needInsertList.size());
|
||||
List<PcdeDetail> slice = needInsertList.subList(i, end);
|
||||
int affected = pcdeDetailMapper.batchInsertIgnore(slice);
|
||||
totalInserted += affected;
|
||||
}
|
||||
|
||||
int skipped = totalTried - totalInserted;
|
||||
return String.format("导入完成:共读取 %d 条,成功导入 %d 条,跳过(可能重复) %d 条。",
|
||||
totalTried, totalInserted, skipped);
|
||||
return String.format("导入完成:共读取 %d 条,文件内重复 %d 条,数据库已存在 %d 条,成功导入 %d 条。",
|
||||
pcdeList.size(), innerRepeatCount, dbRepeatCount, totalInserted);
|
||||
}
|
||||
|
||||
/** 将 pcode 按字符转大写十六进制(与新增接口保持一致) */
|
||||
|
||||
@@ -382,5 +382,84 @@
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
<!-- 新增前查重 -->
|
||||
<select id="selectByWarehouseSceneAndPcode" parameterType="PcdeDetail" resultMap="PcdeDetailResult">
|
||||
SELECT
|
||||
id,
|
||||
pcode,
|
||||
scene,
|
||||
parent_warehouse_code,
|
||||
parent_warehouse_name,
|
||||
warehouse_code,
|
||||
warehouse_name,
|
||||
encoded_id,
|
||||
tag,
|
||||
remark,
|
||||
is_delete,
|
||||
created_by,
|
||||
created_at,
|
||||
updated_by,
|
||||
updated_at
|
||||
FROM pcde_detail
|
||||
WHERE is_delete = 0
|
||||
AND warehouse_code = #{warehouseCode}
|
||||
AND scene = #{scene}
|
||||
AND pcode = #{pcode}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 修改前查重(排除当前id) -->
|
||||
<select id="selectRepeatByWarehouseSceneAndPcode" parameterType="PcdeDetail" resultMap="PcdeDetailResult">
|
||||
SELECT
|
||||
id,
|
||||
pcode,
|
||||
scene,
|
||||
parent_warehouse_code,
|
||||
parent_warehouse_name,
|
||||
warehouse_code,
|
||||
warehouse_name,
|
||||
encoded_id,
|
||||
tag,
|
||||
remark,
|
||||
is_delete,
|
||||
created_by,
|
||||
created_at,
|
||||
updated_by,
|
||||
updated_at
|
||||
FROM pcde_detail
|
||||
WHERE is_delete = 0
|
||||
AND warehouse_code = #{warehouseCode}
|
||||
AND scene = #{scene}
|
||||
AND pcode = #{pcode}
|
||||
AND id != #{id}
|
||||
LIMIT 1
|
||||
</select>
|
||||
<select id="selectExistsForImport" resultMap="PcdeDetailResult">
|
||||
SELECT
|
||||
id,
|
||||
pcode,
|
||||
scene,
|
||||
parent_warehouse_code,
|
||||
parent_warehouse_name,
|
||||
warehouse_code,
|
||||
warehouse_name,
|
||||
encoded_id,
|
||||
tag,
|
||||
remark,
|
||||
is_delete,
|
||||
created_by,
|
||||
created_at,
|
||||
updated_by,
|
||||
updated_at
|
||||
FROM pcde_detail
|
||||
WHERE is_delete = '0'
|
||||
AND
|
||||
<foreach collection="list" item="item" separator=" OR " open="(" close=")">
|
||||
(
|
||||
warehouse_code = #{item.warehouseCode}
|
||||
AND scene = #{item.scene}
|
||||
AND pcode = #{item.pcode}
|
||||
)
|
||||
</foreach>
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user