首页 > 编程语言 >Java导入功能实现

Java导入功能实现

时间:2024-02-21 16:33:05浏览次数:33  
标签:功能 Java String failMsg List private 导入 工单 append

今天记录一下Java实现导入数据到数据,导入失败显示如下,会告诉你哪里出错了。

controller代码实现

    @Operation(summary = "导入工单")
    @PostMapping("/importOrderData")
    public BaseResponse<String> importOrderData(@RequestParam @Parameter(name = "excelFile", description = "属性excel", required = true) MultipartFile excelFile) throws IOException {
        return workOrderService.importOrderData(excelFile);
    }

serviceImpl代码实现

    @Override
    @Transactional
    public BaseResponse<String> importOrderData(MultipartFile multipartFile) throws IOException {
        BaseResponse baseResponse = checkFile(multipartFile);
        if (!baseResponse.resultIsOk()) {
            return baseResponse;
        }
        List<WorkOrderVoImportDto> orderVoImports = EasyExcel.read(multipartFile.getInputStream())
                .head(WorkOrderVoImportDto.class).sheet(0).doReadSync();
        List<WorkOrder> orders = new ArrayList<>();
        List<WorkOrderAudit> orderAudits = new ArrayList<>();
        List<StringBuffer> failMsgList = checkPointParam(orderVoImports,orders,orderAudits);
        if (CollectionUtils.isEmpty(failMsgList)) {
            this.saveBatch(orders);
            workOrderAuditService.saveBatch(orderAudits);
            return BaseResponse.ok();
        }
        return BaseResponse.fail(String.join("", failMsgList));
    }

checkFile ,主要是看下你的文件是否有问题

private BaseResponse<String> checkFile(MultipartFile multipartFile) throws IOException {
        String XLSX = ".xlsx", XLS = ".xlsx";
        if (ObjectUtils.isEmpty(multipartFile)) {
            return BaseResponse.fail("文件不能为空");
        }
        String filename = multipartFile.getOriginalFilename();
        assert filename != null;
        if (!filename.endsWith(XLSX) && !filename.endsWith(XLS)) {
            return BaseResponse.fail("文件格式不对");
        }
        EasyExcel.read(multipartFile.getInputStream(), new CheckWorkOrderListener()).head(WorkOrderVoImportDto.class).sheet(0).doReadSync();
        //校验表头是否一致
        String errorMsg = BizContextProvider.get("errorMsg");
        if (StringUtils.isNotEmpty(errorMsg)) {
            return BaseResponse.fail(errorMsg);
        }
        return BaseResponse.ok();
    }

CheckWorkOrderListener

@Component
public class CheckWorkOrderListener extends AnalysisEventListener<WorkOrderVoImportDto> {

    @Override
    public void invoke(WorkOrderVoImportDto data, AnalysisContext context) {

    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

    }


    /**
     * 获取表头
     *
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        //单行表头验证方式
        List titleList = getExcelTitle(headMap, context);

        // 遍历字段进行判断
        for (Field field : WorkOrderVoImportDto.class.getDeclaredFields()) {
            // 获取当前字段上的ExcelProperty注解信息
            ExcelProperty fieldAnnotation = field.getAnnotation(ExcelProperty.class);
            // 判断当前字段上是否存在ExcelProperty注解
            if (fieldAnnotation != null) {
                // 存在ExcelProperty注解则根据注解的index索引到表头中获取对应的表头名
                Object tile = titleList.get(fieldAnnotation.index());
                // 判断表头是否为空或是否和当前字段设置的表头名不相同
                if ("".equals(tile.toString()) || !tile.toString().equals(fieldAnnotation.value()[0])) {
                    // 如果为空或不相同,则抛出异常不再往下执行
                    BizContextProvider.put("errorMsg", "模板表头错误,请检查导入模板!");
                    return;
                }
            }
        }
    }


    /**
     * 获取表头(一行)
     *
     * @param headMap
     * @param context
     * @return
     */
    public static List getExcelTitle(Map<Integer, String> headMap, AnalysisContext context) {
        List keyList = new ArrayList<>();
        //遍历获取第一行和第二行表头,存入keyList
        Set<Integer> integerSet = headMap.keySet();
        for (int i1 = 0; i1 < integerSet.size(); i1++) {
            keyList.add(headMap.get(i1));
        }
        return keyList;
    }
}
WorkOrderVoImportDto 这个是导入的对象,就是你Excel里面的对象,其中@ExcelProperty注解很重要,尤其是value(excel表头名称)和index(Excel排序字段)
@Data
@AllArgsConstructor
@NoArgsConstructor
@ContentRowHeight(20)
@ColumnWidth(12)
@HeadRowHeight(20)
public class WorkOrderVoImportDto {

    /**
     * 工单编码
     */
    @ExcelProperty(value = "工单编码", index = 0)
    private String workOrderCode;

    /**
     * 产品编码
     */
    @ExcelProperty(value = "产品编码", index = 1)
    private String productCode;

    /**
     * 产品名称
     */
    @ExcelProperty(value = "产品名称", index = 2)
    private String productName;

    /**
     * 生产数量
     */
    @ExcelProperty(value = "计划生产量", index = 3)
    private String productionQuantity;

    /**
     * 生产单位
     */
    @ExcelProperty(value = "单位", index = 4)
    private String productionUnit;

    /**
     * 开始时间
     */
    @ExcelProperty(value = "计划开始时间", index = 5)
    //@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private String startTime;

    /**
     * 结束时间
     */
    @ExcelProperty(value = "计划完成时间", index = 6)
    //@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private String endTime;

   

}

 checkPointParam方法主要两个功能,一个是校验,另外一个是组装好待会要插入到数据库的对象

private List<StringBuffer> checkPointParam(List<WorkOrderVoImportDto> orderVoImports,List<WorkOrder> orders,List<WorkOrderAudit> orderAudits) {
        int index = 1;
        List<StringBuffer> failMsgList = new ArrayList<>(100);
        //StringBuffer commonError = new StringBuffer();
        // 工单编码是否存在校验
        List<String> orderCodes = orderVoImports.stream().map(WorkOrderVoImportDto::getWorkOrderCode).distinct().collect(Collectors.toList());
//        if (orderCodes.size() != orderVoImports.size()){
//            commonError.append("工单编码存在重复数据,");
//            failMsgList.add(commonError);
//        }
        // 去查询数据库是否存在此次导入的工单编码
        if (CollUtil.isNotEmpty(orderCodes)){
            LambdaQueryWrapper<WorkOrder> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(WorkOrder::getWorkOrderCode,orderCodes);
            List<WorkOrder> workOrders = workOrderMapper.selectList(wrapper);
            if (ObjUtil.isNotEmpty(workOrders)){
                List<String> orderCodeList = workOrders.stream().map(WorkOrder::getWorkOrderCode).collect(Collectors.toList());
                String orderStr = "工单号:" + orderCodeList + "已存在,";
                //commonError.append(orderStr);
                failMsgList.add(new StringBuffer(orderStr));
            }
        }
        // 产品编码是否存在校验
        List<String> productCodes = orderVoImports.stream().map(WorkOrderVoImportDto::getProductCode).distinct().collect(Collectors.toList());
        LambdaQueryWrapper<Product> productWrapper = new LambdaQueryWrapper<>();
        productWrapper.in(Product::getProductCode,productCodes);
        List<Product> products = productMapper.selectList(productWrapper);
        if (productCodes.size() != products.size()){
            List<String> collect = products.stream().map(Product::getProductCode).distinct().collect(Collectors.toList());
            if (CollUtil.isNotEmpty(products)){
                // 拿出那个不存在的产品编码
                List<String> diff = productCodes.stream() .filter(e -> !collect.contains(e)).collect(Collectors.toList());
                String productStr = "产品编码:" + diff + "不存在,";
                //commonError.append(productStr);
                failMsgList.add(new StringBuffer(productStr));
            }
        }
        for (WorkOrderVoImportDto orderVoImport : orderVoImports) {
            WorkOrder workOrder = new WorkOrder();
            WorkOrderAudit workOrderAudit = new WorkOrderAudit();
            BeanUtil.copyProperties(orderVoImport,workOrder);
            index++;
            StringBuffer failMsg = new StringBuffer();
            StringBuffer failMsgDetails = new StringBuffer();
            String workOrderCode = orderVoImport.getWorkOrderCode();
            // 工单编码校验
            if (StringUtils.isEmpty(workOrderCode)){
                failMsg.append("工单编码不可为空,");
            }else if (workOrderCode.length() > 40){
                failMsg.append("工单编码长度不可超过40,");
            }
            // 产品编码校验
            String productCode = orderVoImport.getProductCode();
            if (StringUtils.isEmpty(productCode)){
                failMsg.append("产品编码不可为空,");
            }else if (productCode.length() > 20){
                failMsg.append("产品编码长度不可超过20,");
            }
            // 产品名称校验
            String productName = orderVoImport.getProductName();
            if (StringUtils.isEmpty(productName)){
                failMsg.append("产品名称不可为空,");
            }else if (productCode.length() > 20){
                failMsg.append("产品名称长度不可超过20,");
            }
            // 计划生产量校验
            String productionQuantity = orderVoImport.getProductionQuantity();
            if (ObjUtil.isEmpty(productionQuantity)){
                failMsg.append("计划生产量不可为空,");
            }else {
                try {
                    int i = Integer.parseInt(productionQuantity);
                    if (i < 0 || i > 99999){
                        failMsg.append("计划生产量数据有误,");
                    }
                    workOrder.setProductionQuantity(i);
                }catch (Exception e){
                    failMsg.append("计划生产量数据有误,");
                }
            }
            // 单位校验
            String productionUnit = orderVoImport.getProductionUnit();
            if (StringUtils.isEmpty(productionUnit)){
                failMsg.append("单位不可为空,");
            }else if (productCode.length() > 20){
                failMsg.append("单位长度不可超过20,");
            }
            // 计划开始时间校验
            String startTime = orderVoImport.getStartTime();
            boolean startTimeFlag = true;
            LocalDateTime parseStart = null;
            if (ObjUtil.isEmpty(startTime)){
                startTimeFlag = false;
                failMsg.append("计划开始时间不可为空,");
            }else {
                try {
                    parseStart = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    workOrder.setStartTime(parseStart);
                }catch (Exception e){
                    startTimeFlag = false;
                    failMsg.append("计划开始时间数据有误,");
                }
            }
            // 计划完成时间校验
            String endTime = orderVoImport.getEndTime();
            boolean endTimeFlag = true;
            LocalDateTime parseEnd = null;
            if (ObjUtil.isEmpty(endTime)){
                endTimeFlag = false;
                failMsg.append("计划完成时间不可为空,");
            }else {
                try {
                    parseEnd = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    workOrder.setEndTime(parseEnd);
                }catch (Exception e){
                    endTimeFlag = false;
                    failMsg.append("计划完成时间数据有误,");
                }
            }
            // 开始时间和完成时间对比
            if (startTimeFlag && endTimeFlag){
                boolean after = parseStart.isAfter(parseEnd);
                if (after){
                    failMsg.append("计划开始时间不能在计划完成时间之后,");
                }
            }
            // 初始化一些数据,方便后面的插入数据
            workOrder.setOrderStatus(OrderStatusEnum.WAIT_PRODUCT.getCode());
            workOrder.setAuditStatus(OrderAuditStatusEnum.WAIT_AUDIT.getCode());
            workOrder.setDataSources(0); // 0 手动创建
            orders.add(workOrder);
            workOrderAudit.setAuditStatus(OrderAuditStatusEnum.WAIT_AUDIT.getCode());
            workOrderAudit.setWorkOrderCode(orderVoImport.getWorkOrderCode());
            orderAudits.add(workOrderAudit);
            if (StringUtils.isNotEmpty(failMsg)) {
                int start = failMsg.lastIndexOf(",");
                failMsg.replace(start, start + 1, ";");
                String str = "第【" + index + "】行:";
                failMsgDetails.append(str).append(failMsg);
                failMsgList.add(failMsgDetails);
            }
        }
        return failMsgList;
    }
View Code

下面是workOrder对象

@Data
@Schema(description = "工单表")
@Accessors(chain = true)
@TableName("work_order")
public class WorkOrder extends BaseEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键id
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    @Schema(description = "主键id")
    private Long id;

    /**
     * 工单编码
     */
    @Schema(description = "工单编码")
    private String workOrderCode;

    /**
     * 产品编码
     */
    @Schema(description = "产品编码")
    private String productCode;

    /**
     * 生产数量
     */
    @Schema(description = "生产数量")
    private Integer productionQuantity;

    /**
     * 生产单位
     */
    @Schema(description = "生产单位")
    private String productionUnit;

    /**
     * 开始时间
     */
    @Schema(description = "开始时间")
    private LocalDateTime startTime;

    /**
     * 结束时间
     */
    @Schema(description = "结束时间")
    private LocalDateTime endTime;

    /**
     * 工单状态:0 待生产, 1 生产中, 2 已完成
     */
    @Schema(description = "工单状态")
    private Integer orderStatus;

    /**
     * 数据来源:0 手动创建, 1 同步创建
     */
    @Schema(description = "数据来源")
    private Integer dataSources;

    /**
     * 审核状态:0 待审核, 1 审核同意, 2 审核拒绝;方便查询,去维护这个字段
     */
    private Integer auditStatus;



}

下面是workAudit对象

@Data
@Schema(description = "工单审批表")
@Accessors(chain = true)
@TableName("work_order_audit")
public class WorkOrderAudit extends BaseEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键id
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 工单编码
     */
    private String workOrderCode;

    /**
     * 审核状态:0 待审核, 1 审核同意, 2 审核拒绝
     */
    private Integer auditStatus;

    /**
     * 审核意见
     */
    private String auditOpinion;



}

Excel测试数据

 

如果数据没问题,就可以导入到数据库,也检查下数据是否有问题。测试的时候先造没问题的主流程数据,然后再测试有问题的数据,看下你写的代码是否可以正常校验到对应数据。

以上笔记为导入过程

 

标签:功能,Java,String,failMsg,List,private,导入,工单,append
From: https://www.cnblogs.com/qwg-/p/18025557

相关文章

  • 《Effective Java》阅读笔记-第九章
    EffectiveJava阅读笔记第九章通用编程第57条将局部变量的作用域最小化将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能。将局部变量的作用域最小化,最好的办法就是在第一次使用变量的地方声明它。几乎每一个局部变量都应该进行初始化。第5......
  • 《Effective Java》阅读笔记-第八章
    EffectiveJava阅读笔记第八章方法第49条检查参数的有效性基于“发生错误后应尽快检测出错误”这一通用原则,应对方法的参数进行检查。Java7中增加了Objects.requireNonNull方法,可以很方便的对参数进行null检查并抛出异常:publicvoidsomeMethod(Stringargs){ar......
  • 《Effective Java》阅读笔记-第十一章
    EffectiveJava阅读笔记第十一章并发第78条同步访问共享的可变数据多线程访问变量时,需要进行同步,否则就会产生并发问题。同步代码块、加锁等或者直接不共享变量,也就是将可变数据限制在单个线程内。ThreadLocal这种第79条避免过度同步为了避免活性失败和安全性失败......
  • 《Effective Java》阅读笔记-第十章
    EffectiveJava阅读笔记第十章异常第69条只针对异常的情况才使用异常说白了就是不要吧你的业务逻辑用异常来写。举个反例比如用抛出异常来遍历一个数组:try{inti=0;while(true){range[i++].doSomething();}}catch(ArrayIndexOutOfBoun......
  • 《Effective Java》阅读笔记-第十二章
    EffectiveJava阅读笔记第十二章序列化第85条其他方法优先于Java本身的序列化Java本身的序列化漏洞过多,很容易被攻击。避免被序列化攻击的最好方式就是不要反序列化任何字节流,并且新的系统中没有任何理由使用Java本身的序列化。JSON和Protobuf是两种优秀的序列化......
  • java类初始化及代码块加载顺序连根拔起
    说明相信很多人对于java中父子继承关系中,子类实例化调用过程中,代码块的执行顺序都容易忘记或搞混,尤其是java初级笔试题或面试题最容易出这类题目,让人恨得牙痒痒!!!本文就一次性将其连根铲除,看完你就不会有这个烦恼了,哈哈。先引用一下骨灰级大作《Java编程思想》的复用章节Java......
  • 一键脚本破解最新版 idea 步骤,开启学习java 之旅,好好好
    效果:步骤1、idea安装:直接在官网下载最新idea-2022.2.3.dwg(:官网地址,然后根据安装引导一步一步完成安装即可,完成后打开idea看到如下效果表示idea安装成功!如图发现idea需要注册!这里我们先不管,直接关闭idea准备激活!步骤2、下载最新的破解包https://pan.baidu.com/s/1iQby9......
  • Hutool - 简化Java编程的法宝,让工作更高效
    一、在项目的pom.xml的dependencies中加入以下内容:<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.0.7</version></dependency>非Maven项目的话就自己百度下载一下jar包,导入即可。二、StrUtil看这里名字也应该明白了,......
  • 承前启后,Java对象内存布局和对象头
    承前启后,Java对象内存布局和对象头大家好,我是小高先生。在我之前的一篇文章《并发编程防御装-锁(基础版)》中,我简要介绍了锁的基础知识,并解释了为什么Java中的任何对象都可以作为锁。在那里,我提到了对象头中有一个指向ObjectMonitor的指针,但没有深入探讨Java对象的内存结构。本文将......
  • Java的配置
    环境变量配置找到配置的位置右击此电脑-->属性-->高级系统设置-->环境变量-->系统变量配置Path环境变量(必须配置的)(目的:为了可以在任意目录下找到javac和java命令)方式1:直接在Path变量中添加jdk的bin目录的完整路径系统变量-->Path-->新建-->D:\soft\java\jdk\bin方式2:(推荐......