超简单通用的Java上传Excel,批量导入数据工具类
程序员文章站
2024-01-11 17:08:28
使用Java上传Excel文件批量导入数据到数据库。相信大家对Java POI 上传Excel读取并导入数据库的工具类屡见不鲜,今天我写了一份比较通用的工具类,这时候有小伙伴问,通用在哪里呢?那我先介绍一下我发现大多的导入存在的一些问题:一、导入需要创建存入数据库表对应的实体类,并于Excel中的列对应,导致一个导入方法只能导入一个表。二、导入大都是获取当前文件的本地路径,但是许多浏览器做了安全限制,本地路径不能直接获取。只能拿到"c:\fakepath…"三、重复代码量大,如...
使用Java上传Excel文件批量导入数据到数据库。
相信大家对Java POI 上传Excel读取并导入数据库的工具类屡见不鲜,今天我写了一份比较通用的工具类,这时候有小伙伴问,通用在哪里呢?
那我先介绍一下我发现大多的导入存在的一些问题:
一、导入需要创建存入数据库表对应的实体类,并于Excel中的列对应,导致一个导入方法只能导入一个表。 |
---|
二、导入大都是获取当前文件的本地路径,但是许多浏览器做了安全限制,本地路径不能直接获取。只能拿到"c:\fakepath…" |
三、重复代码量大,如果有多张表需要导入,那么需要拷贝很多次。并且实体对应的字段需要修改。 |
以上问题,我这个工具类都得到了解决。是一个通用的Excel导入工具类。
我的项目是springboot-mybatisPlus-Mysql的项目
首先要导入两个POI的依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
下面看代码。以及代码如何使用;加注释一共90行。如果各路大佬有好的修改意见~欢迎留言!
package com.util;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import java.lang.reflect.Field;
import java.util.*;
/**
* @Author: SONGTiank
* @Description: Excel导入工具类
* @Date: 2020/11/9 14:54
* @Version: 1.0
*/
public class ReadExcelByPOI<T> {
//泛型类,T:虚拟类型;
public List<T> readExcelByPOI(T t, MultipartFile filePath){
//创建一个对应的空的泛型集合
List<T> infoList = new ArrayList<>();
// 反射出类类型(方便后续做操作)
Class c = t.getClass();
// 获得该类所有自己声明的字段,包括该类中继承 Serializable 的UID
Field[] fs = c.getDeclaredFields();
//map集合是存读取到的excel行数据
Map<String, List<String>> map =new HashMap<String,List<String>>();
try{
//获取到页面传递过来文件的文件名截取后缀
int index = filePath.getOriginalFilename().lastIndexOf(".");
String postfix = filePath.getOriginalFilename().substring(index+1);
Workbook workbook =null;
//根据后缀判断使用 hssf或 xssf
if("xls".equals(postfix)){
workbook =new HSSFWorkbook(filePath.getInputStream());
}else if("xlsx".equals(postfix)){
workbook =new XSSFWorkbook(filePath.getInputStream());
}
//获取Excel表中的数据开始,默认只有sheet1 一页数据 存入map↓-------------------
Sheet sheet = workbook.getSheetAt(0);
//总的行数
int rows = sheet.getLastRowNum();
//总的列数--->最后一列为null则有问题,读取不完整,将表头的数目作为总的列数,没有的则补为null
int columns = sheet.getRow(0).getLastCellNum();
//先列后行
for(int i =1; i <= rows; i++){
Row row = sheet.getRow(i);
if(null!= row && row.getFirstCellNum()==-1){//这一行是空行,不读取
continue;
}
List<String> contentList =new ArrayList<String>();
contentList.clear();
for(int j =0; j < columns; j++){
if(row.getCell(j)!=null){
row.getCell(j).setCellType(Cell.CELL_TYPE_STRING);
contentList.add(row.getCell(j).getStringCellValue());
}else{
contentList.add("");
}
}
map.put("entityInfo"+i, contentList);
}
//获取Excel表中的数据结束,默认只有sheet1 一页数据 ↑-------------------
//遍历map集合,封装成bean
for(Map.Entry<String,List<String>> entry : map.entrySet()){
t = (T) c.newInstance();
List<String> list = entry.getValue();
int size = list.size();//map中封装的列数
//fs.length 是你传入实体类的所有字段个数,包括该类中继承 Serializable 的UID
//所以这里最后比对一下,将长度判断相等,或者去除Excel中没有的字段
//这里我将Serializable 的UID 去除,所以 i 从1开始;
for (int i = 1; i < fs.length; i++) {
/*
* fs[i].getName():获得字段名
*
* f:获得的字段信息
*/
Field f = t.getClass().getDeclaredField(fs[i].getName());
// 参数true 可跨越访问权限进行操作
f.setAccessible(true);
/*
* f.getType().getName():获得字段类型的名字
*/
// 判断其类型进行赋值操作
if (f.getType().getName().equals(String.class.getName())) {
//因为i从1开始,然后list的角标需要从0开始,所以这里减去1,保障不会角标越界;
//注意:excel模板中的列数是和实体类的字段对应排列的
f.set(t, list.get(i-1));
} else if (f.getType().getName().equals(int.class.getName())) {
f.set(t, Integer.parseInt(list.get(i-1)));
}
}
//将完整的实体存入集合返回;接收到后只需要循环调用insert方法即可
infoList.add(t);
}
}catch(Exception e){
e.printStackTrace();
}
return infoList;
}
}
下面看一下我的测试,首先是前端页面
<!--页面的按钮,input的file上传,并作限制只允许上传.xls,.xlsx文件-->
<input type="file" id="filePath" name="filePath" accept=".xls,.xlsx" onchange="cois()">
<!--js代码,这里直接使用的内容改变事件,上传后就立马进行读取-->
function cois() {
formData = new FormData();
//uploadFile就是后台接收的文件参数名称
formData.append('uploadFile', $('#filePath')[0].files[0]);
$.ajax({
type: "POST",
url: "/syxx/startContent/getPathToExcel",
data: formData,
contentType: false,
processData: false,
success: function (data) {
alert("success");
}
});
}
后端页面
/**
* excel导入
*/
@RequestMapping("/getPathToExcel")
@ResponseBody
public boolean getPathToExcel(@RequestParam("uploadFile") MultipartFile uploadFile){
//创建readExcelByPOI工具类,泛型为导入的实体类
ReadExcelByPOI<StartContent> readExcelByPOI = new ReadExcelByPOI<StartContent>();
//传入导入的实体类,以及文件
List<StartContent> startContents = readExcelByPOI.readExcelByPOI(new StartContent(), uploadFile);
//做一个简单的判断,然后进行写入;
if(startContents.size()>0){
for (StartContent startContent : startContents) {
startContentService.insert(startContent);
}
}
return true;
}
StartContent实体类字段
Excel对应字段
执行结束后即可成功存入数据库
至此导入代码结束
有什么问题欢迎留言,后期会作改善
本文地址:https://blog.csdn.net/weixin_43238452/article/details/109582185