EasyExcel 批量导入并校验数据

这篇具有很好参考价值的文章主要介绍了EasyExcel 批量导入并校验数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

EasyExcel 批量导入并校验数据

一、pom

      <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.7</version>
        </dependency>

二、使用步骤

1.导入对象

日期形式的字段因为校验需要,提供了String类型的字段,再转换赋值给真正的数据库字段对象,如果不考虑校验问题可直接转换@ExcelProperty(value = "处罚信息公示日期", index = 5, converter = LocalDateConverter.class)

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.time.LocalDate;

/**
 * 信用信息修复
 *
 * @author huaiyu.zhang
 * @since 2023-04-19 10:59:49
 */
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("信用信息修复")
public class CreditInfoExcelInReq implements Serializable {

    private static final long serialVersionUID = 370622351109421619L;


    @ApiModelProperty("${column.comment}")
    @ExcelIgnore
    private String id;

    @ApiModelProperty("企业名称")
    @Length(max = 30, message = "企业名称:最多可输入30个字")
    @NotBlank(message = "企业名称不能为空")
    @ExcelProperty(index = 0, value = "企业名称")
    private String companyName;

    @ApiModelProperty("统一社会信用代码")
    @Length(min = 18, max = 18, message = "统一社会信用代码必须18位")
    @NotBlank(message = "统一社会信用代码不能为空")
    @ExcelProperty(index = 1, value = "统一社会信用代码")
    private String creditCode;

    @ExcelProperty(index = 2, value = "行政区划--地市")
    @NotBlank(message = "行政区划--地市不能为空")
    private String districtCodeCity;

    @ExcelProperty(index = 3, value = "行政区划--区/县")
    private String districtCodeCountry;

    @ApiModelProperty("行政区划")
    @NotBlank(message = "行政区划不能为空")
    @ExcelIgnore
    private String districtCode;

    @NotBlank(message = "失信行为类别不能为空")
    @ExcelProperty(index = 4, value = "失信行为类别")
    private String typeCodeName;

    @ApiModelProperty("失信行为类别 0一般失信行为 1-严重失信行为")
    @NotBlank(message = "失信行为类别不能为空")
    @ExcelIgnore
    private String typeCode;

    @ExcelProperty(index = 5, value = "处罚信息公示日期")
    @Pattern(regexp = "[0-9]{4}-[0-9]{2}-[0-9]{2}", message = "处罚信息公示日期格式必须为yyyy-MM-dd")
    private String punishTimeOri;

    @ApiModelProperty("处罚信息公示日期")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    @ExcelIgnore
    private LocalDate punishTime;

    @ApiModelProperty("信用修复部门")
    @Length(max = 20, message = "信用修复部门:最多可输入20个字")
    @ExcelIgnore
    private String repairDepartment;

    @ApiModelProperty("信用修复完成日期")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    @ExcelIgnore
    private LocalDate repairTime;

    @ApiModelProperty("状态 0-未修复 1-已修复")
    @ExcelIgnore
    private String status;

    @ApiModelProperty("备注")
    @Length(max = 300, message = "备注:最多300字")
    @ExcelIgnore
    private String mark;

}

2.读入数据并保存

读取数据后Validation校验,校验通过直接保存(如果数据已经存在,则copy excel外其他字段后删除原数据,导入新数据),校验失败则返回失败行数(这里也可以导出校验失败详情)

默认规则:设置excel最大导入数据行数为LIST_COUNT = 1000;
如果需要导入更多数据,改大这个值即可,也可invoke时分批读取数据
但是每次执行完invoke后都会执行doAfterAllAnalysed下的saveData,那么校验逻辑将只针对本批次数据进行校验,如校验失败,会直接返回给前端。后续批次由于异常被抛出不会执行(可更改校验逻辑,或错误信息返回形式)

Listener 端代码:

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.gsafety.bg.sv.model.dto.req.CreditInfoExcelInReq;
import com.gsafety.bg.sv.model.dto.req.CreditInfoReq;
import com.gsafety.bg.sv.model.dto.resp.BasDistrictResp;
import com.gsafety.bg.sv.model.po.CreditInfoPO;
import com.gsafety.bg.sv.service.CreditInfoService;
import com.gsafety.bg.sv.service.constant.CreditTypeEnum;
import com.gsafety.bg.sv.service.utils.MappingConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import java.time.LocalDate;
import java.util.*;

/**
 * @author huaiyu.zhang
 * @since 2023-6-5 0005 17:10
 */

@Slf4j
public class CreditInfoExcelDataListener extends AnalysisEventListener<CreditInfoExcelInReq> {

    private final Integer LIST_COUNT = 1000;

    List<CreditInfoExcelInReq> list = new ArrayList<>(LIST_COUNT);

    // 由于监听器只能通过new的方式创建,所以可以通过构造器传入dao层对象
    private final CreditInfoService service;

    public CreditInfoExcelDataListener(CreditInfoService service) {
        this.service = service;
    }

    @Override
    public void invoke(CreditInfoExcelInReq req, AnalysisContext analysisContext) {
        //每读取一行数据都会调用一次
        list.add(req);
        if (list.size() >= LIST_COUNT) {
            throw new ExcelAnalysisException("当前excel数据量不得大于" + LIST_COUNT + "条!");
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        //所有数据解析完毕执行该方法
        // 防止导入空的Excel
        if (analysisContext.readRowHolder().getRowIndex() <= 0) {
            throw new ExcelAnalysisException("当前excel无数据!");
        }
        saveData();
    }

    protected void saveData() {
        Set<String> errorRow = new HashSet<>();
        List<BasDistrictResp> districtList = MappingConvertUtil.getDistrictList();
        list.forEach(l -> {
            Integer row = list.indexOf(l) + 2;
            if (ObjectUtils.isEmpty(l.getDistrictCodeCountry())) {
                Optional<BasDistrictResp> opt = districtList.stream().filter(d -> l.getDistrictCodeCity().equals(d.getDistName())).findFirst();
                if (!opt.isPresent()) {
                    errorRow.add(row.toString());
                } else {
                    l.setDistrictCode(opt.get().getDistCode());
                }
            } else {
                String parentCode = districtList.stream().filter(d -> l.getDistrictCodeCity().equals(d.getDistName())).findFirst()
                        .orElse(BasDistrictResp.builder().distCode("").build()).getDistCode();
                Optional<BasDistrictResp> opt = districtList.stream().filter(d -> parentCode.equals(d.getParentCode()) && l.getDistrictCodeCountry().equals(d.getDistName())).findFirst();
                if (!opt.isPresent()) {
                    errorRow.add(row.toString());
                } else {
                    l.setDistrictCode(opt.get().getDistCode());
                }
            }
            l.setTypeCode(CreditTypeEnum.getCode(l.getTypeCodeName()));
            Set<ConstraintViolation<Object>> validate = Validation.buildDefaultValidatorFactory().getValidator().validate(l);
            //用于存储验证后的错误信息
            if (validate.size() > 0) {
                errorRow.add(row.toString());
                //防止相同数据indexof定位错误
                l.setId(UUID.randomUUID().toString());
            } else {
                //日期格式校验成功后再转换punishTimeOri,否则直接报错
                l.setPunishTime(LocalDate.parse(l.getPunishTimeOri()));
                CreditInfoReq req = new CreditInfoReq();
                //构造新数据覆盖旧数据
                BeanUtils.copyProperties(l, req);
                Optional<CreditInfoPO> opt = service.loadByCreditCode(l.getCreditCode());
                if (opt.isPresent()) {
                    req.setRepairTime(opt.get().getRepairTime());
                    req.setStatus(opt.get().getStatus());
                    req.setMark(opt.get().getMark());
                    req.setRepairDepartment(opt.get().getRepairDepartment());
                    //删除旧数据
                    service.delete(opt.get().getId());
                }
                l.setId(service.add(req));
            }
            if (row - 1 == list.size() && errorRow.size() > 0) {
                throw new ExcelAnalysisException("部分导入成功,其中第" + String.join(",", errorRow) + "行导入失败!", null);
            }
        });
    }
}

service 端代码:

    public String importData(MultipartFile file) {
        CreditInfoExcelDataListener listener = new CreditInfoExcelDataListener(this);
        InputStream inputStream;
        try {
            inputStream = file.getInputStream();
            EasyExcel.read(inputStream, CreditInfoExcelInReq.class,
                    listener).sheet().doRead();
            return "全部导入成功!";
        } catch (IOException e) {
            throw new BusinessCheckException("Excel 文件流读取失败");
        } catch (ExcelAnalysisException e) {
            return e.getMessage();
        } catch (Exception e) {
            throw new BusinessException("数据导入失败", e);
        }
    }

EasyExcel 批量导入并校验数据

EasyExcel 批量导入并校验数据文章来源地址https://www.toymoban.com/news/detail-479936.html

到了这里,关于EasyExcel 批量导入并校验数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • EasyExcel导入和导出数据

    1.cmtroller 调用service方法,完成导出 2.service 调用工具类的方法完成导出 传入response,标题控制类(标题名称,合并的列数),员工列表,文件名称,excel的标题名称,要导出的数据类 3.工具类中的方法 4.控制标题类 这个类控制数据之前的显示内容 效果 2022-10-28 乱码解决 因为文件

    2023年04月09日
    浏览(38)
  • SpringBoot使用EasyExcel批量导出500万数据

    记录下学习SpringBoot使用EasyExcel批量导出百万数据。留着以后备用。 本地环境mysql安装的5.7版本,项目使用jdk1.8版本,项目使用的mysql驱动版本为8.0版本。 这一篇博客内容代码基于我的这篇博客: SpringBoot使用mybatis批量新增500万数据到mysql数据库Demo,在自己这篇博客的代码上做

    2024年02月12日
    浏览(39)
  • 数据导入导出(POI以及easyExcel)

            将一些数据库信息导出为Excel表格         将Excel表格数据导入数据库         大量数据的导入导出操作 常⽤的解决⽅案为: Apache POI 与阿⾥巴巴 easyExcel Apache POI 是基于 Office Open XML 标准( OOXML )和 Microsoft 的 OLE 2 复合⽂档 格式( OLE2 )处理各种⽂件格式的

    2024年02月13日
    浏览(38)
  • 基于EasyExcel的数据导入导出(复制可用)

    目录   前言: 新建SpringBoot项目,引入下面的依赖 数据导入导出执行原理和思路: 用户端逻辑: 后台开发逻辑: 代码实现 下拉框策略 批注策略 数据读取监听 Excel工具类 创建导入数据模板类 创建数据导出模板 Web接口 结果展示 模板下载 数据导入 数据导出   代码复制粘贴

    2024年02月05日
    浏览(45)
  • 使用EasyExcel实现模板下载、数据导入功能

    1.在你的工程下添加模板文件 2.编写代码实现下载功能 controller serviceImpl 好了,到这里,一个简单的下载模板功能就实现了。不过我在项目运行中遇到了一些坑,下面记录一下。 3.项目中遇到的坑:excel文件在springboot的maven项目下打了jar包后损坏 4.解决办法:试了很多种,主要

    2024年02月13日
    浏览(48)
  • EasyExcel导出带下拉选数据的Excel数据导入模板

    #因为项目中需要导入一些信息,但是这些信息比较不常见,且在项目字典数据中维护有这些数据,所以在导出模板的时候,把这些数据一并导出,可以减少用户的编写,避免在导入的时候因为数据错误,发生一些业务问题 直接开始 1、以岗位类型为例,展示数据的实现方式

    2024年02月03日
    浏览(46)
  • 【二十四】springboot使用EasyExcel和线程池实现多线程导入Excel数据

      springboot篇章整体栏目:  【一】springboot整合swagger(超详细 【二】springboot整合swagger(自定义)(超详细) 【三】springboot整合token(超详细) 【四】springboot整合mybatis-plus(超详细)(上) 【五】springboot整合mybatis-plus(超详细)(下) 【六】springboot整合自定义全局异常

    2023年04月08日
    浏览(65)
  • java实现excel的导入导出(带参数校验:非空校验、数据格式校验)

    本次封装引入阿里开源框架EasyExcel,EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。 github地址:GitHub - alibaba/easyexcel: 快速、简洁、解决大文件内存溢出的java处理Excel工具 。 64M内存20秒读取75M(46W行25列)的Excel(3.0.2

    2024年02月01日
    浏览(66)
  • Elasticsearch 批量导入数据

    **Elasticsearch**是一款非常高效的全文检索引擎。 **Elasticsearch**可以非常方便地进行数据的多维分析,所以大数据分析领域也经常会见到它的身影,生产环境中绝大部分新产生的数据可以通过应用直接导入,但是历史或初始数据可能会需要单独处理,这种情况下可能遇到需要导

    2023年04月11日
    浏览(40)
  • 【大数据】Hive 中的批量数据导入

    在博客【大数据】Hive 表中插入多条数据 中,我简单介绍了几种向 Hive 表中插入数据的方法。然而更多的时候,我们并不是一条数据一条数据的插入,而是以批量导入的方式。在本文中,我将较为全面地介绍几种向 Hive 中批量导入数据的方法。 overwrite :表示覆盖表中已有数

    2024年02月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包