欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

超简单通用的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;
    }
}

下面看一下我的测试,首先是前端页面
超简单通用的Java上传Excel,批量导入数据工具类

<!--页面的按钮,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实体类字段
超简单通用的Java上传Excel,批量导入数据工具类
Excel对应字段
超简单通用的Java上传Excel,批量导入数据工具类
执行结束后即可成功存入数据库
至此导入代码结束
有什么问题欢迎留言,后期会作改善

本文地址:https://blog.csdn.net/weixin_43238452/article/details/109582185