java动态导入excel按照表头生成数据库表

1、创建接口接收文件


//controller层
@PostMapping("/importExcel1")public void importExcel1(HttpServletRequest request, MultipartFile file) {try {waterMeterService.importExcel1(request,file);} catch (Exception e) {throw new RuntimeException(e);}}//service层
void importExcel1(HttpServletRequest request, MultipartFile file);//实现类层
@Overridepublic void importExcel1(HttpServletRequest request, MultipartFile file) {try {//获取用户信息String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf("."));//文件后缀String fileSuffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));//1.首先获取文件名生成一条记录String directoryName = StringUtils.isEmpty("sheet1") ? fileName : "sheet1";
//            String uuid = createDataSets(directoryName, null, excelReq.getId(), sysUser, excelReq.getDataType(), excelReq.getAddressType());String uuid = UUID.randomUUID().toString();EasyExcel.read(file.getInputStream(), new ConfigFilterListener(waterMeterMapper)).sheet(0).doRead();} catch (IOException e) {throw new RuntimeException(e);}}

2、创建easyexcel导入监听器

package com.wang.test.listener;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.wang.test.mapper.WaterMeterMapper;
import lombok.SneakyThrows;
import org.springframework.scheduling.annotation.Async;import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;/*** @BelongsPackage: com.wang.test.listener* @Author: wangqian* @CreateTime: 2024-01-24  09:51:59* @Describe:*/
public class ConfigFilterListener implements ReadListener<LinkedHashMap<String, String>> {/*** 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 1000;private String tableName;//表名private String columnNames;//字段名private List<LinkedHashMap<String, String>> dataSetList = new ArrayList<>();@Resourceprivate WaterMeterMapper waterMeterMapper;//构造函数public ConfigFilterListener(WaterMeterMapper waterMeterMapper) {this.waterMeterMapper = waterMeterMapper;}/*** 这个每一条数据解析都会来调用* 这个接口作用是将excel数据全部添加到dataSetList中,然后达到BATCH_COUNT的时候触发新增数据操作*/@SneakyThrows@Overridepublic void invoke(LinkedHashMap<String, String> linkedHashMap, AnalysisContext analysisContext) {//log.info("解析到一条数据:{}", linkedHashMap);LinkedHashMap<String, String> map = new LinkedHashMap<>();map.put("uuid", UUID.randomUUID().toString());Set set = linkedHashMap.keySet();Iterator iterator = set.iterator();while (iterator.hasNext()) {Object next = iterator.next();map.put(next.toString(), linkedHashMap.get(next));}dataSetList.add(map);//  达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (dataSetList.size() >= BATCH_COUNT) {//创建插入语句StringBuffer sb = new StringBuffer("insert into ");sb.append(this.tableName + " (");sb.append(this.columnNames + " )");// 这里也要保存数据,确保最后遗留的数据也存储到数据库batchInsert(sb.toString(), dataSetList);// 存储完成清理 listdataSetList.clear();}}/*** 所有数据解析完成了 都会来调用*这个方法的作用就是将excel数据插入到生成的表中如果数据大于BATCH_COUNT,则不足与BATCH_COUNT的会做新增操作* @param analysisContext*/
//    @SneakyThrows@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {if (dataSetList.size() > 0) {//创建插入语句StringBuffer sb = new StringBuffer("insert into ");sb.append(this.tableName + " (");//表名称sb.append(this.columnNames + " )");//插入的数据// 这里也要保存数据,确保最后遗留的数据也存储到数据库batchInsert(sb.toString(), dataSetList);dataSetList.clear();}}/**** 读取Excel表格表头* 这个方法的作用就是获取表头,创建数据库表* @param headMap* @param context*/@Overridepublic void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {try {//每次执行前需求清除上次的结果this.columnNames = null;// 当前sheet的名称 编码获取类似String tableName = context.readSheetHolder().getSheetName();int tableCount = waterMeterMapper.existsTable(tableName);//判断表名是否存在List<String> heads = new ArrayList<>();heads.add("uuid");if (tableCount > 0) {//按照业务需求是创建新表还是提示错误tableName += "_"+System.currentTimeMillis();}StringBuffer createTableStr = new StringBuffer("CREATE TABLE ");createTableStr.append(tableName);createTableStr.append(" (uuid varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,");Collection<ReadCellData<?>> values = headMap.values();//这个是我自己写的,大家按照自己的需求来设置for (int i = 0; i < values.size(); i++) {createTableStr.append("column_"+(i+1) + " varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,");heads.add("column_"+(i+1));}
//这个value.getStringValue()会获取表头的数据,生成的表字段则是按照表头配置的
//            for (ReadCellData<?> value : values) {
//                createTableStr.append(value.getStringValue() + " varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,");
//                heads.add(value.getStringValue());
//            }createTableStr.append("PRIMARY KEY (`uuid`) USING BTREE)");int updateCount = waterMeterMapper.createTable(createTableStr.toString());if (updateCount != 0) {throw new RuntimeException("创建数据库表失败!");}//创建成功后,得插入一条对应记录
//            createDataSets(tableName, tableName, uuid, sysUser, dataType, sort, addressType);this.tableName = tableName;this.columnNames = heads.stream().collect(Collectors.joining(","));} catch (Exception ex) {//waterMeterService.removeById(uuid);//throw new RuntimeException("导入失败!请联系管理员!");}}@Overridepublic boolean hasNext(AnalysisContext context) {return true;}@Asyncpublic void batchInsert(String tableString, List<LinkedHashMap<String, String>> list){try {waterMeterMapper.insertTableData(tableString, list);} catch (Exception e) {throw new RuntimeException(e);}}
}

3、mapper层

 //判断表是否存在int existsTable(@Param("tableName") String tableName);//生成新的表int createTable(@Param("tableString")String tableString);void insertTableData(@Param("tableString") String tableString,@Param("dataSetList") List<LinkedHashMap<String, String>> dataSetList);

4、xml层


<!--    判断表是否存在--><select id="existsTable" resultType="java.lang.Integer">SELECT COUNT(*) FROM information_schema.tables WHERE table_name = #{tableName} AND table_schema = 'test';</select><!--    创建新表--><update id="createTable">${tableString}</update><!--    新增数据--><insert id="insertTableData">insert into ${tableString} values<foreach collection='dataSetList' item='line' index='index'  separator=','><foreach collection='line.values' item='value' open='(' separator=',' close=')'>#{value}</foreach></foreach></insert>

5、里面有些逻辑按照需求来处理,比如表重复,中间出现异常等
后面查询这些数据的时候,可以做配置表(建立一张表),文件名和表名做配置关系,如果要查询这些动态导入数据,则需要知道查哪些表,还有别的需求可以讨论,一起学习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/645464.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

selenium执行出现异常,SessionNotCreatedException ChromeDriver only supports

问题现状&#xff1a; 运行程序报错&#xff1a; selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 114 Current browser version is 121.0.6167.85 with binary path /App…

重构改善既有代码的设计-学习(四):简化条件逻辑

1、分解条件表达式&#xff08;Decompose Conditional&#xff09; 可以将大块代码分解为多个独立的函数&#xff0c;根据每个小块代码的用途&#xff0c;为分解而得的新函数命名。对于条件逻辑&#xff0c;将每个分支条件分解成新函数还可以带来更多好处&#xff1a;可以突出条…

cartopy绘图特征

文章目录 添加特征add_feature区域截取 添加特征 cartopy中最基础的地图绘制函数是coastlines&#xff0c;即海岸线线条图&#xff0c;这很复合我们的绘图直觉&#xff0c;毕竟陆地和海洋的边缘&#xff0c;是最清晰的地理特征。而在此之上&#xff0c;还可以通过add_feature函…

Java 面试题库

基础篇 面向对象的特征 封装&#xff08;Encapsulation&#xff09;&#xff1a; 封装是指将对象的数据&#xff08;属性&#xff09;和行为&#xff08;方法&#xff09;结合在一起&#xff0c;形成一个独立的实体。对象的数据被隐藏在内部&#xff0c;只能通过定义好的接口&…

【嵌入式学习】网络通信基础-项目篇:简单UDP聊天室

源码已在GitHub开源&#xff1a;0clock/LearnEmbed-projects/chat 实现的功能 客户端功能&#xff1a; 上线发送登录的用户名[yes] 发送消息和接收消息[yes] quit退出 服务器端功能&#xff1a; 统计用户上线信息&#xff0c;放入链表中[yes] 接收用户信息并给其他用户发送消…

Windows11 鼠标拖动文件到CMD控制终端窗口无效,无法显示具体文件路径

对于某些用户来说&#xff0c;他们可能会在Windows 11上遇到鼠标拖动文件到CMD控制终端时&#xff0c;无法显示具体文件路径的情况。 系统更新&#xff0c;习惯基础操作无效了&#xff0c;真的有点烦&#xff0c;不会提问就无计可施。 果然善于提问&#xff0c;才有果子吃 问…

架构师之路(十五)计算机网络(网络层协议)

前置知识&#xff08;了解&#xff09;&#xff1a;计算机基础。 作为架构师&#xff0c;我们所设计的系统很少为单机系统&#xff0c;因此有必要了解计算机和计算机之间是怎么联系的。局域网的集群和混合云的网络有啥区别。系统交互的时候网络会存在什么瓶颈。 ARP协议 地址解…

分类预测 | Matlab实现GRU-Attention-Adaboost基于门控循环单元融合注意力机制的Adaboost数据分类预测/故障识别

分类预测 | Matlab实现GRU-Attention-Adaboost基于门控循环单元融合注意力机制的Adaboost数据分类预测/故障识别 目录 分类预测 | Matlab实现GRU-Attention-Adaboost基于门控循环单元融合注意力机制的Adaboost数据分类预测/故障识别分类效果基本描述程序设计参考资料 分类效果 …

SpringBoot项目多数据源配置与MyBatis拦截器生效问题解析

在日常项目开发中&#xff0c;由于某些原因&#xff0c;一个服务的数据源可能来自不同的库&#xff0c;比如&#xff1a; 对接提供的中间库&#xff0c;需要查询需要的数据同步数据&#xff0c;需要将一个库的数据同步到另一个库&#xff0c;做为同步工具的服务对接第三方系统…

服务器渲染+自定义模块+mysql操作

1.服务器渲染 A.第一步&#xff0c;导入模块库和第三方库 npm init npm --registry https://registry.npmmirror.com install art-template moment B.第二步&#xff0c;调整html文件 <!DOCTYPE html> <html lang"en"><head><meta charset…

K8s-应用管理(环境变量,Job)

容器传参 构建一个测试镜像 FROM ubuntu CMD ["sleep"&#xff0c;"5"]运行这个容器发现睡眠了5秒以后退出&#xff0c;如果我们希望自己指定可以直接在docker后面加命令覆盖&#xff0c;写法如下 docker run sleeper sleep 10上面的过程显得有些不合理…

Redis面试

1.说说什么事redis Redis是一种基于键值对的NoSql数据库。 Redis中的value支持string&#xff08;字符串&#xff09;、hahs&#xff08;哈希&#xff09;、list、set、zset&#xff08;有序集合&#xff09;、bitmaps&#xff08;位图&#xff09;&#xff0c;HyperLoglog等数…

ACwing算法基础入门代码合集

ACwing算法基础入门代码合集 快速排序 786.第k个数 //第k个数 //算法思想&#xff1a;基于快速排序&#xff08;分治&#xff09; #include<iostream> using namespace std; #define N 100010 int Partition(int a[], int low, int high); int quicksort(int a[], int…

Java基础数据结构之排序

一.排序 1.什么是稳定性 假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&#xff0c;这些记录的相对次序保持 不变&#xff0c;即在原序列中&#xff0c; r[i]r[j] &#xff0c;且 r[i] 在 r[j] 之前&#xff0c;而在排序后的序…

php 文件上传

目录 1 php.ini 配置文件的修改 2.系统返回码详解 错误级别 4.上传简单示例 5.php代码简单优化 1 php.ini 配置文件的修改 配置项说明file_uploads on 为 开启文件上传功能&#xff0c; off 为关闭 post_max_size 系统允许的 POST 传参的最大值 &#xff0c;默认 8M upl…

【JSON2WEB】03 go的模板包html/template的使用

Go text/template 是 Go 语言标准库中的一个模板引擎&#xff0c;用于生成文本输出。它使用类似于 HTML 的模板语言&#xff0c;可以将数据和模板结合起来&#xff0c;生成最终的文本输出。 Go html/template包实现了数据驱动的模板&#xff0c;用于生成可防止代码注入的安全的…

电信宽带配置动态域名和端口映射

需求: 家宽映射动态域名访问内网服务 动态域名:18081>电信光猫:18081>Openwrt软路由:18081>主机192.168.3.172:8081 目前网络结构&#xff1a; 电信光猫192.168.1.1 Openwrt软路由192.168.3.1 主机192.168.3.172上8081端口起了一个nginx-docker服务 前置条件&#x…

【JavaWeb】MVC架构模式

文章目录 MVC是什么&#xff1f;一、M &#xff1a;Model 模型层二、V&#xff1a;View 视图层三、C&#xff1a;Controller 控制层四、非前后端分离MVC五、前后端分离MVC总结 MVC是什么&#xff1f; MVC&#xff08;Model View Controller&#xff09;是软件工程中的一种**软件…

【supervisor】unix:///tmp/supervisor.sock no such file

问题 supervisor在正常安装完时运行正常&#xff0c;但隔一段时间后出现了故障&#xff0c;重启后报&#xff1a; unix:///tmp/supervisor.sock no such file 原因是 supervisor 默认配置会把 socket 文件和 pid 守护进程生成在Linux的/tmp/目录下&#xff0c;/tmp/目录是缓存…

网页首页案例(使用框架:继上一篇博客结尾)

文章目录 新认识的快捷键1.先写好组件并导入App.vue2.往组件中一个一个填内容3.整体静态完成后&#xff0c;发现某些小部分相同&#xff0c;其实可以分装成小组件4.最后通过js动态渲染 新认识的快捷键 1.Ctrl滚轮按住往下拖可以部分选中 .用同样的方法选中下面的111&#xff0…