EasyExcel 批量导入并校验数据
文章目录
- 前言
- 一、pom
- 二、使用步骤
- 1.导入对象
- 2.读入数据并保存
前言
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}")@ExcelIgnoreprivate 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 = "行政区划不能为空")@ExcelIgnoreprivate String districtCode;@NotBlank(message = "失信行为类别不能为空")@ExcelProperty(index = 4, value = "失信行为类别")private String typeCodeName;@ApiModelProperty("失信行为类别 0一般失信行为 1-严重失信行为")@NotBlank(message = "失信行为类别不能为空")@ExcelIgnoreprivate 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")@ExcelIgnoreprivate LocalDate punishTime;@ApiModelProperty("信用修复部门")@Length(max = 20, message = "信用修复部门:最多可输入20个字")@ExcelIgnoreprivate String repairDepartment;@ApiModelProperty("信用修复完成日期")@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")@ExcelIgnoreprivate LocalDate repairTime;@ApiModelProperty("状态 0-未修复 1-已修复")@ExcelIgnoreprivate String status;@ApiModelProperty("备注")@Length(max = 300, message = "备注:最多300字")@ExcelIgnoreprivate 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;}@Overridepublic void invoke(CreditInfoExcelInReq req, AnalysisContext analysisContext) {//每读取一行数据都会调用一次list.add(req);if (list.size() >= LIST_COUNT) {throw new ExcelAnalysisException("当前excel数据量不得大于" + LIST_COUNT + "条!");}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {//所有数据解析完毕执行该方法// 防止导入空的Excelif (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 批量导入并校验数据
文章目录 前言一、pom二、使用步骤1.导入对象2.读入数据并保存 前言 EasyExcel 批量导入并校验数据 一、pom <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.7</version></depend…...

亚马逊、Allegro卖家建立属于自己的测评系统,实现批量优质账号养成
卖家搭建一套完整的测评系统,卖家自己能够养出批量优质账号,并完全掌控真实买家的浏览、加购、下单和评价等风控数据规律。我们的系统能够自主加速推广,防御反击,同时节省运营成本,实现高效的测评运营。 我们的系统支…...

springboot的目录结构作用
springboot单体项目结构大概如下。 代码都在src/main下, java是后端代码 java下最基本的包 dao(mapper) entity(model) service controller 其他的包根据项目需求扩展。 resources下是配置文件。 如果不是前后端分离,resources下放的是静态文件…...

微信小程序基础使用-请求数据并渲染
小程序基本使用-请求数据并渲染 小程序模板语法-数据绑定 在js中定义数据 Page({data: {isOpen: true,message: hello world!} })小程序的data是一个对象,不同于vue的data是一个函数 在模块中获取使用数据 小程序中使用 {{}} 实现数据与模板的绑定 内容绑定&a…...

代码随想录训练营Day55| 392.判断子序列 ;115.不同的子序列
392.判断子序列 class Solution {public boolean isSubsequence(String s, String t) {int m s.length();int n t.length();if(m>n) return false;int[][] dp new int[m1][n1];dp[0][0]0;for(int i1;i<m;i){for(int j1;j<n;j){if(s.charAt(i-1)t.charAt(j-1)){dp[i…...

网络作业9【计算机网络】
网络作业9【计算机网络】 前言推荐网络作业9一. 单选题(共12题,36分)二. 多选题(共1题,3分)三. 填空题(共2题,10分)四. 阅读理解(共1题,17分&…...
C++ QT 上传图片至mysql数据库
以下是一个简单的C QT上传图片至MySQL数据库的代码示例: #include <QtSql> #include <QFile> #include <QByteArray> int main() { //连接数据库 QSqlDatabase db QSqlDatabase::addDatabase("QMYSQL"); …...

2023去水印小程序saas系统源码修复独立版v1.0.3+uniapp前端
🎈 限时活动领体验会员:可下载程序网创项目短视频素材 🎈 🎉 有需要的朋友记得关赞评,阅读文章底部来交流!!! 🎉 ✨ 源码介绍 一个基于uniapp写的小程序,后端…...

【ChatGPT】数据科学 ChatGPT Cheat Sheet 书籍分享(阿里云盘下载)
封皮 以下为书中部分内容的机器翻译 我们的重要提示指南 1. 以 AI 角色的描述开始提示。 例如,“你是{x}”或“我希望你扮演{x}”。如果您不确定,请尝试“你是一个有帮助的助手”。 例如,您是 OpenAI 的数据科学家,您正在研究大型…...
使用 Docker-compose 搭建lnmp
服务编排: 应用编排: 单机环境下:shell/python脚本多机/集群环境下:ansible、saltstack、pubbet docker容器编排: 单机:docker-compose多机/集群:docker swarm,mesos marathon&a…...

chatgpt赋能python:Python中的矩阵合并方法:介绍和使用方法
Python中的矩阵合并方法: 介绍和使用方法 矩阵合并是Python编程中常用的操作之一,特别是针对数据分析、机器学习和深度学习等领域。Python提供了多种方法来合并矩阵,本文将介绍这些方法并分享如何在实际应用中使用它们。 普通矩阵合并 最基础的矩阵合…...

Java动态代理:优化静态代理模式的灵活解决方案
文章目录 代理模式定义具体实现分析优缺点 优化使用动态代理解决优化相关知识动态代理种类场景应用 代理模式 定义 代理模式,为其他对象提供一种代理以控制对这个对象的访问 具体实现 代理模式的具体实现描述可以分为以下几个步骤: 创建抽象对象接…...

四种Bootloader程序安全机制设计
正文 大家周末好,我是bug菌~ 不管是玩单片机还是嵌入式linux,基本上都会接触到bootloader,所以bootloader程序也是一个关键的组件,进行硬件初始化,应用程序的合法性、完成性检测、升级功能等等都与其息息相关。 像一些…...

【DBA 警世录之习惯性命令---读书笔记】
👈【上一篇】 💖The Begin💖点点关注,收藏不迷路💖 【下一篇】👉 🔻【💣 话题引入:既然 DBA 这个职业如此危险,那么哪些习惯是 DBA 必须养成的呢&#x…...

Vue中如何进行状态持久化(LocalStorage、SessionStorage)
Vue中如何进行状态持久化(LocalStorage、SessionStorage)? 在Vue应用中,通常需要将一些状态进行持久化,以便在用户关闭浏览器或刷新页面后,仍能保留之前的状态。常见的持久化方式包括LocalStorage和Sessio…...

【30天熟悉Go语言】6 Go 复杂数据类型之指针
文章目录 一、前言二、数据类型总览三、指针1、特殊运算符& *2、内存角度来看指针3、使用指针修改数据4、指针使用的注意事项5、对比着看Java的引用类型 三、总结 一、前言 Go系列文章: GO开篇:手握Java走进Golang的世界2 Go开发环境搭建、Hello Wor…...
Linux内核使用红黑树的场景
进程调度队列 (Process Scheduling):内核需要对进程按照一定的调度策略进行排队,以便更好地利用 CPU 的时间片。因此,内核使用红黑树作为查找和管理进程调度队列的数据结构,以支持快速的查找、插入和删除操作。 文件系统 (File S…...

遗留的 AppSec 工具迷失在云端
随着应用程序开发步伐的加快,IT 和安全团队正在对旧的应用程序安全(AppSec) 工具失去信心。 根据 Backslash 对 300 名 CISO、AppSec 经理和工程师的调查,遗留工具无法跟上并陷入永远的追赶游戏。 影响是深远的,大多数组织都看到云原生 App…...

直流稳压电源与信号产生电路(模电速成)
目录 一、直流稳压电源 1、直流稳压电路 2、串联型稳压电路 3、集成稳压电路 二、信号产生电路 1、振荡电路 2、波形发生器 一、直流稳压电源 1、直流稳压电路 直流电源由 变压器、整流、滤波、稳压 四部分组成 整流:将交流变为直流 滤波:减小…...

0202性能分析-索引-MySQL
1 索引语法 创建索引 CREATE [UNIQUE|FULLTEXT] INDEX index_name ON table_name(index_column_name,...);Index_name:规范为idx_表名_字段名... 查看索引 SHOW INDEX FROM table_name;删除索引 DROP INDEX index_name ON table_name;按照下列要求,创建…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...

数据挖掘是什么?数据挖掘技术有哪些?
目录 一、数据挖掘是什么 二、常见的数据挖掘技术 1. 关联规则挖掘 2. 分类算法 3. 聚类分析 4. 回归分析 三、数据挖掘的应用领域 1. 商业领域 2. 医疗领域 3. 金融领域 4. 其他领域 四、数据挖掘面临的挑战和未来趋势 1. 面临的挑战 2. 未来趋势 五、总结 数据…...