package com.zy.asrs.importexcle; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.core.common.Cools; import com.core.common.DateUtils; import com.core.common.SnowflakeIdWorker; import com.core.exception.CoolException; import com.zy.asrs.entity.Review; import com.zy.asrs.entity.ReviewDetl; import com.zy.asrs.service.ReviewDetlService; import com.zy.asrs.service.ReviewService; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import java.util.*; /** * @author pang.jiabao * @description 导入订单监听器 * @createDate 2024/9/2 9:56 */ @Slf4j public class ImportReviewListener extends AnalysisEventListener { /** * 每隔1000条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 */ private static final int BATCH_COUNT = 2000; private int count = 0; private long orderId; List list = new ArrayList<>(); /** * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。 */ private final PlatformTransactionManager transactionManager; private ReviewService reviewService; private ReviewDetlService reviewDetlService; private final SnowflakeIdWorker snowflakeIdWorker; private final Long userId; private TransactionStatus transactionStatus; /** * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来 */ public ImportReviewListener(PlatformTransactionManager transactionManager, ReviewService reviewService, ReviewDetlService reviewDetlService, SnowflakeIdWorker snowflakeIdWorker, Long userId) { this.transactionManager = transactionManager; this.reviewService = reviewService; this.reviewDetlService = reviewDetlService; this.snowflakeIdWorker = snowflakeIdWorker; this.userId = userId; } private Set uniquePackNos = new HashSet<>(); // 用于去重包装组号 @SneakyThrows @Override public void invoke(ImportReviewDto data, AnalysisContext context) { log.info("解析到第 {} 条数据:{}", ++count, JSON.toJSONString(data)); if (Cools.isEmpty(data.getColumn1())) { log.warn("规格型号,跳过该行!"); return; } if (Cools.isEmpty(data.getColumn2())) { log.info("重复的包装组号:{},跳过", data.getColumn5()); return; } if (Cools.isEmpty(data.getColumn3())) { log.info("重复的包装组号:{},跳过", data.getColumn7()); return; } // 首次出现,记录并处理 uniquePackNos.add(data.getColumn1()); String time = DateUtils.convert(new Date(), DateUtils.yyyyMMddHHmmss_F); Review review = reviewService.selectOne(new EntityWrapper().eq("order_no", data.getColumn1())); if (review == null) { review = new Review(); review.setUuid(String.valueOf(snowflakeIdWorker.nextId())); review.setOrderNo(data.getColumn1()); review.setOrderTime(time); review.setSettle(1L); review.setStatus(1); review.setCreateBy(userId); review.setCreateTime(new Date()); reviewService.insert(review); review = reviewService.selectOne(new EntityWrapper().eq("order_no", data.getColumn1())); } data.setOrderId(review.getId()); list.add(data); if (list.size() >= BATCH_COUNT) { saveData(); list.clear(); } } /** * 所有数据解析完成了 都会来调用 */ @Override public void doAfterAllAnalysed(AnalysisContext context) { // 这里也要保存数据,确保最后遗留的数据也存储到数据库 if (list.size() > 0) { saveData(); } log.info("所有数据解析完成!"); } private static final int MAX_BATCH_SIZE = 50; // 建议 100~200,根据字段数控制 /** * 分批存储数据库,避免SQL Server参数上限(2100)错误 */ private void saveData() { log.info("{}条数据,开始存储数据库!", list.size()); log.info("数据:{},", JSON.toJSONString(list)); List orderDetlList = new ArrayList<>(); for (ImportReviewDto importOrderDto : list) { List reviewDetls = reviewDetlService.selectList(new EntityWrapper().eq("order_no", importOrderDto.getColumn1()).eq("specs", importOrderDto.getColumn2()).eq("anfme", importOrderDto.getColumn4()).eq("batch", importOrderDto.getColumn3())); if (reviewDetls != null && reviewDetls.size() > 0) { throw new CoolException(importOrderDto.getColumn1() + "=批次:" + importOrderDto.getColumn7() + "规格:" + importOrderDto.getColumn4() + "该明细已存在!"); } ReviewDetl orderDetl = new ReviewDetl(); orderDetl.setOrderNo(importOrderDto.getColumn1()); orderDetl.setSpecs(importOrderDto.getColumn2()); orderDetl.setBatch(importOrderDto.getColumn3()); orderDetl.setAnfme(importOrderDto.getColumn4()); orderDetl.setMatnr(importOrderDto.getColumn5()); orderDetl.setMaktx(importOrderDto.getColumn6()); orderDetl.setUnit(importOrderDto.getColumn7()); //orderDetl.set(importOrderDto.getColumn6()); orderDetl.setModel(importOrderDto.getColumn9()); orderDetl.setDeadTime(importOrderDto.getColumn10()); orderDetl.setOrderId(importOrderDto.getOrderId()); orderDetl.setCreateBy(9527L); orderDetl.setCreateTime(new Date()); orderDetl.setUpdateBy(9527L); orderDetl.setUpdateTime(new Date()); orderDetl.setStatus(1); orderDetlList.add(orderDetl); } // ✅ 关键点:分批提交 for (ReviewDetl d : orderDetlList) { reviewDetlService.insert(d); } log.info("存储数据库成功!"); } /** * 解析出现错误会进入该方法 具体看源代码或文档 */ @Override public void onException(Exception exception, AnalysisContext context) throws Exception { log.error("处理异常:" + exception.getMessage()); throw exception; } }