1.调整导入建垛功能逻辑,优化执行速度

master
x_z 3 years ago
parent a8ff3575a0
commit fcb3c60142

@ -178,7 +178,12 @@ public class StackOrderController {
return ResultVOUtils.error(ResultEnum.PARAM_VERIFY_FALL, "请上传文件!");
}
ThreadUtil.execAsync(() -> {
stackOrderService.importStackOrder(importStackOrderRequest.getFilePath());
try {
stackOrderService.importStackOrder(importStackOrderRequest.getFilePath(), importStackOrderRequest.getCustomerId());
} catch (Exception e) {
log.error("导入建垛失败", e);
throw new RuntimeException(e.getMessage());
}
});
return ResultVOUtils.success("导入成功");
}

@ -5,6 +5,8 @@ import com.glxp.udi.admin.entity.product.StackCode;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface StackCodeDao extends BaseMapper<StackCode> {
@ -30,4 +32,11 @@ public interface StackCodeDao extends BaseMapper<StackCode> {
* @return
*/
long countByCode(@Param("code") String code);
/**
*
*
* @param list
*/
void batchInsert(List<StackCode> list);
}

@ -13,4 +13,9 @@ public class ImportStackOrderRequest {
*/
private String filePath;
/**
* ID
*/
private String customerId;
}

@ -2,6 +2,7 @@ package com.glxp.udi.admin.service.product;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
@ -33,7 +34,6 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
@ -133,14 +133,9 @@ public class StackOrderService {
*
* @param filePath
*/
public void importStackOrder(String filePath) {
long t1 = System.currentTimeMillis();
public void importStackOrder(String filePath, String customerId) throws InterruptedException {
List<StackCodeVo> list = EasyExcel.read(filePath).head(StackCodeVo.class).sheet().doReadSync();
long t2 = System.currentTimeMillis();
log.info("解析数据用时:{}", t2 - t1);
if (CollUtil.isEmpty(list)) {
log.error("解析垛码excel文件数据为空");
throw new RuntimeException("垛码excel文件数据为空");
@ -149,59 +144,60 @@ public class StackOrderService {
//条码集合
List<String> codeList = list.stream().map(StackCodeVo::getCode).collect(Collectors.toList());
List<StackCode> stackCodes = new ArrayList<>(list.size());
//校验码在数据库中是否重复
//每1000个一次查询按照码数量分批
int batchNum = codeList.size() / 1000 + (codeList.size() % 1000 != 0 ? 1 : 0);
CountDownLatch checkCodeCDL = new CountDownLatch(batchNum);
//线程计数器
CountDownLatch countDownLatch = new CountDownLatch(list.size());
for (StackCodeVo vo : list) {
executorService.submit(() -> {
log.info("添加任务");
if (StrUtil.isBlank(vo.getOrderId()) || StrUtil.isBlank(vo.getCode())) {
log.error("数据为空,数据不规范");
throw new RuntimeException("垛码数据格式错误,解析失败");
}
for (int i = 1; i <= batchNum; i++) {
int start = (i - 1) * 1000;
int end = i * 1000;
List<String> codePage = codeList.subList(start, end);
List<String> codeTemp = new ArrayList<>(codeList.size());
BeanUtil.copyProperties(codeList, codeTemp);
QueryWrapper<StackCode> wrapper = new QueryWrapper<>();
wrapper.in("code", codePage);
//判断此条码在数据库或者表中是否重复,如果有重复,则直接返回错误数据
codeTemp.remove(vo.getCode()); //先移除自身
if (codeTemp.contains(vo.getCode()) || stackCodeDao.countByCode(vo.getCode()) > 0) {
log.error("条码重复,重复的条码和流水号为:{}{}", vo.getCode(), vo.getOrderId());
executorService.submit(() -> {
Long count = stackCodeDao.selectCount(wrapper);
if (count > 0) {
log.error("条码重复,导入失败");
throw new RuntimeException("条码重复");
}
//构造码数据
StackCode stackCode = new StackCode(vo.getOrderId(), vo.getCode());
UdiEntity udi = FilterUdiUtils.getUdi(stackCode.getCode());
BeanUtil.copyProperties(udi, stackCode);
stackCodes.add(stackCode);
log.info("执行结束");
//线程执行结束,计数器 -1
countDownLatch.countDown();
//任务计数器 -1
checkCodeCDL.countDown();
});
}
//阻塞到线程池任务执行结束
try {
countDownLatch.await();
log.info("数据封装任务执行完毕");
} catch (Exception e) {
log.error("解析封装失败失败", e);
throw new RuntimeException("解析封装数据异常");
//等待查重结束
checkCodeCDL.await();
//对集合去重,若集合中的数据存在重复,则导入失败
int oldLength = codeList.size();
ArrayList<String> codes = CollUtil.distinct(codeList);
if (codes.size() < oldLength) {
log.error("条码重复");
throw new RuntimeException("条码重复");
}
//封装码数据
List<StackCode> stackCodes = new ArrayList<>();
list.forEach(vo -> {
if (StrUtil.isBlank(vo.getOrderId()) || StrUtil.isBlank(vo.getCode())) {
log.error("数据为空,数据不规范");
throw new RuntimeException("垛码数据格式错误,解析失败");
}
//构造码数据
StackCode stackCode = new StackCode(vo.getOrderId(), vo.getCode());
UdiEntity udi = FilterUdiUtils.getUdi(stackCode.getCode());
BeanUtil.copyProperties(udi, stackCode);
stackCodes.add(stackCode);
});
long t3 = System.currentTimeMillis();
log.info("构造数据用时:{}", t3 - t2);
Map<String, List<StackCode>> stacks = stackCodes.stream().collect(Collectors.groupingBy(StackCode::getOrderIdFk));
//根据每一个流水号,创建单据,生成条码
String customerId = String.valueOf(customerService.getCustomerId());
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, TransactionIsolationLevel.READ_COMMITTED);
StackCodeDao mapper = sqlSession.getMapper(StackCodeDao.class);
for (String serialNum : stacks.keySet()) {
StackOrder stackOrder = new StackOrder();
String stackId = idUtil.getStackId(customerId);
@ -212,21 +208,15 @@ public class StackOrderService {
//插入垛数据
stackOrderDao.insert(stackOrder);
List<StackCode> data = stacks.get(serialNum);
List<StackCode> saveDataList = new CopyOnWriteArrayList<>(data);
saveDataList.parallelStream().forEach(stackCode -> {
stackCode.setOrderIdFk(stackId);
mapper.insert(stackCode);
});
data.forEach(stackCode -> stackCode.setOrderIdFk(stackId));
sqlSession.commit();
//按照指定长度切分集合,批量插入
List<List<StackCode>> listList = ListUtil.split(data, 5000);
for (List<StackCode> stackCodeList : listList) {
stackCodeDao.batchInsert(stackCodeList);
}
}
sqlSession.close();
long t4 = System.currentTimeMillis();
log.info("插入数据用时:{}", t4 - t3);
log.info("全程用时:{}", t4 - t1);
//导入成功,删除数据文件
FileUtil.del(filePath);
}

@ -15,11 +15,11 @@ public class FilterUdiUtils {
public static UdiEntity getUdi(String data) {
if (data != null && data.length() > 2) {
if (data.substring(0, 2).equals("MA")) {
if (data.startsWith("MA")) {
return getZGCUdi(data);
} else if (data.substring(0, 2).equals("01")) {
} else if (data.startsWith("01")) {
return getGS1Udi(data);
} else if (data.substring(0, 1).equals("#")) {
} else if (data.charAt(0) == '#') {
return getGLXPUdi(data);
}
}
@ -83,7 +83,7 @@ public class FilterUdiUtils {
batchNo = data.substring(34, data.length());
}
}else if (data.length() >= 34 && data.substring(32, 34).equals("21")) {
} else if (data.length() >= 34 && data.substring(32, 34).equals("21")) {
serialNo = data.substring(34, data.length());
}
} else if (data.length() >= 26 && data.substring(24, 26).equals("10")) {

@ -8,10 +8,29 @@
</delete>
<select id="countByOrderId" resultType="java.lang.Long">
select count(*) from stack_code where orderIdFk = #{orderId}
select count(*)
from stack_code
where orderIdFk = #{orderId}
</select>
<select id="countByCode" resultType="long">
select count(*) from stack_code where code = #{code}
select count(*)
from stack_code
where code = #{code}
</select>
<insert id="batchInsert">
insert into stack_code (code, orderIdFk, batchNo, produceDate, expireDate, serialNo, nameCode) values
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.code},
#{item.orderIdFk},
#{item.batchNo},
#{item.produceDate},
#{item.expireDate},
#{item.serialNo},
#{item.nameCode}
)
</foreach>
</insert>
</mapper>
Loading…
Cancel
Save