Apache POI操作批量导入MySQL数据库


Posted in Servers onJune 21, 2022

poi介绍:

Apache POI是用Java编写的免费开源的跨平台的Java API,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能,其中使用最多的就是使用POI操作Excel文件。

POI使用到的相关maven依赖坐标如下:

<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>

POI的相关操作结果

HSSF - 提供读写Microsoft Excel XLS格式档案的功能
XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能
HWPF - 提供读写Microsoft Word DOC格式档案的功能
HSLF - 提供读写Microsoft PowerPoint格式档案的功能
HDGF - 提供读Microsoft Visio格式档案的功能
HPBF - 提供读Microsoft Publisher格式档案的功能
HSMF - 提供读Microsoft Outlook格式档案的功能

1、POI操作入门案例

1.1、从Excel文件读取数据1

使用POI可以从一个已经存在的Excel文件中读取数据

前提需要建立一个需要读取的表格数据进行读取

/**
 * 使用poi读取表格数据
 * @throws Exception
 */
@Test
public void test1() throws Exception {
    // 1、加载指定的文件进行读取
    XSSFWorkbook excel = new XSSFWorkbook(new FileInputStream("C:\\Users\\zhong\\Desktop\\poi.xlsx"));
    // 2、读取表格中的Sheet页,通过索引决定
    XSSFSheet sheetAt = excel.getSheetAt(0);
    // 3、读取Sheet页中的行数据
    for (Row row : sheetAt) {
        // 4、读取每一行数据的单元格数据(如果涉及到类型装转换的可能出现报错消息,后期通过代码进行判断即可)
        for (Cell cell : row) {
            System.out.print(cell+"   ");
        }
        System.out.println();
    }
    // 5、关闭读取文件的流
    excel.close();
}

输出结果如下:

姓名   省份   城市   
张三   广东   高州   
李四   四川   成都   

POI操作Excel表格封装了几个核心对象:

XSSFWorkbook:工作簿
XSSFSheet:工作表
Row:行
Cell:单元格

1.2、从Excel文件读取数据2

还有一种方式就是获取工作表最后一个行号,从而根据行号获得行对象,通过行获取最后一个单元格索引,从而根据单元格索引获取每行的一个单元格对象,代码如下:

/**
 * 使用poi读取文件的第二种方式
 * @throws Exception
 */
@Test
public void test2() throws Exception {
    // 1、加载指定的文件进行读取
    XSSFWorkbook excel = new XSSFWorkbook(new FileInputStream("C:\\Users\\zhong\\Desktop\\poi.xlsx"));
    // 2、读取表格中的Sheet页,通过索引决定
    XSSFSheet sheetAt = excel.getSheetAt(0);
    // 3、获取当前工作表中最后一个行号,注意行号是从0开启的
    int lastRowNum = sheetAt.getLastRowNum();
    // 4、遍历获取到的行号
    for (int i = 0; i <= lastRowNum; i++) {
        // 5、根据行号获取到每一行的数据
        XSSFRow row = sheetAt.getRow(i);
        // 6、获取到当前最后一个单元格索引
        short lastCellNum = row.getLastCellNum();
        // 7、遍历当前的单元格获取到具体的数据
        for (int j = 0; j < lastCellNum; j++) {
            // 获取到单元格的对象
            XSSFCell cell = row.getCell(j);
            // 输出获取到的数据
            System.out.print(cell + "   ");
        }
        System.out.println();
    }
    // 8、释放资源
    excel.close();
}

1.3、向Excel文件写入数据

使用POI可以在内存中创建一个Excel文件并将数据写入到这个文件,最后通过输出流将内存中的Excel文件下载到磁盘

/**
 * poi写出数据到磁盘
 */
@Test
public void test3() throws Exception {
    // 1、创建工作簿
    XSSFWorkbook excel = new XSSFWorkbook();
    // 2、创建工作簿中的表对象
    XSSFSheet sheet = excel.createSheet("创建表");
    // 3、创建第一行(表头)
    XSSFRow row1 = sheet.createRow(0);
    // 4、在行中创建单元格数据
    row1.createCell(0).setCellValue("姓名");
    row1.createCell(1).setCellValue("省份");
    row1.createCell(2).setCellValue("城市");
    row1.createCell(3).setCellValue("年龄");
    // 5、创建第二行
    XSSFRow row2 = sheet.createRow(1);
    // 6、创建第6行的数据
    row2.createCell(0).setCellValue("张三");
    row2.createCell(1).setCellValue("辽宁");
    row2.createCell(2).setCellValue("上海");
    row2.createCell(3).setCellValue("50");
    // 7、创建一个字节输出流,将数据保存到本地
    FileOutputStream fileOutputStream = new FileOutputStream(new File("C:\\Users\\zhong\\Desktop\\aaa.xlsx"));
    excel.write(fileOutputStream);
    fileOutputStream.flush();
    // 8、关闭输出
    excel.close();
    System.out.println("数据导出成功");
}

2、使用POI批量导入数据到MySQL数据库

创建一个数据库的表t_ordersetting

-- auto-generated definition
create table t_ordersetting
(
    id           int auto_increment
        primary key,
    orderDate    date null comment '约预日期',
    number       int  null comment '可预约人数',
    reservations int  null comment '已预约人数'
)
    charset = utf8;

批量导入预约设置信息操作过程:

1、点击模板下载按钮下载Excel模板文件

2、将预约设置信息录入到模板文件中

3、点击上传文件按钮将录入完信息的模板文件上传到服务器

4、通过POI读取上传文件的数据并保存到数据库

创建对应的实体类

public class OrderSetting implements Serializable{
    private Integer id ;
    private Date orderDate;//预约设置日期
    private int number;//可预约人数
    private int reservations ;//已预约人数

    public OrderSetting() {
    }

    public OrderSetting(Date orderDate, int number) {
        this.orderDate = orderDate;
        this.number = number;
    }
}

2.1、创建导入数据的Excel模板文件

目的是为了统一管理导入的数据格式

Apache POI操作批量导入MySQL数据库

修改页面提供一个下载批量导入数据的模板按钮

Apache POI操作批量导入MySQL数据库

//下载模板文件
downloadTemplate(){
    window.location.href="../../template/ordersetting_template.xlsx" rel="external nofollow" ;
}

文件上传前端代码实现

<el-upload action="/ordersetting/upload.do"
           name="excelFile"
           :show-file-list="false"
           :on-success="handleSuccess"
           :before-upload="beforeUpload">
    <el-button type="primary">上传文件</el-button>
</el-upload>

提交函数

// 上传之前进行文件格式校验
beforeUpload(file){
    const isXLS = file.type === 'application/vnd.ms-excel';
    if(isXLS){
        return true;
    }
    const isXLSX = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    if (isXLSX) {
        return true;
    }
    this.$message.error('上传文件只能是xls或者xlsx格式!');
    return false;
},
// 上传成功提示
handleSuccess(response, file) {
    if(response.flag){
        this.$message({
            message: response.message,
            type: 'success'
        });
    }else{
        this.$message.error(response.message);
    }
    console.log(response, file, fileList);
},

2.2、批量上传文件的后端代码编写

关于上传文件一般网上都会有很多的工具类可以下载使用,也就是别人将已经封装好的代码拿出来分享给大家使用的

package com.zcl.utils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
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;

public class POIUtils {
    private final static String xls = "xls";
    private final static String xlsx = "xlsx";
    private final static String DATE_FORMAT = "yyyy/MM/dd";
    /**
     * 读入excel文件,解析后返回
     * @param file
     * @throws IOException
     */
    public static List<String[]> readExcel(MultipartFile file) throws IOException {
        //检查文件
        checkFile(file);
        //获得Workbook工作薄对象
        Workbook workbook = getWorkBook(file);
        //创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回
        List<String[]> list = new ArrayList<String[]>();
        if(workbook != null){
            for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){
                //获得当前sheet工作表
                Sheet sheet = workbook.getSheetAt(sheetNum);
                if(sheet == null){
                    continue;
                }
                //获得当前sheet的开始行
                int firstRowNum  = sheet.getFirstRowNum();
                //获得当前sheet的结束行
                int lastRowNum = sheet.getLastRowNum();
                //循环除了第一行的所有行
                for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){
                    //获得当前行
                    Row row = sheet.getRow(rowNum);
                    if(row == null){
                        continue;
                    }
                    //获得当前行的开始列
                    int firstCellNum = row.getFirstCellNum();
                    //获得当前行的列数
                    int lastCellNum = row.getPhysicalNumberOfCells();
                    String[] cells = new String[row.getPhysicalNumberOfCells()];
                    //循环当前行
                    for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){
                        Cell cell = row.getCell(cellNum);
                        cells[cellNum] = getCellValue(cell);
                    }
                    list.add(cells);
                }
            }
            workbook.close();
        }
        return list;
    }

    //校验文件是否合法
    public static void checkFile(MultipartFile file) throws IOException{
        //判断文件是否存在
        if(null == file){
            throw new FileNotFoundException("文件不存在!");
        }
        //获得文件名
        String fileName = file.getOriginalFilename();
        //判断文件是否是excel文件
        if(!fileName.endsWith(xls) && !fileName.endsWith(xlsx)){
            throw new IOException(fileName + "不是excel文件");
        }
    }
    public static Workbook getWorkBook(MultipartFile file) {
        //获得文件名
        String fileName = file.getOriginalFilename();
        //创建Workbook工作薄对象,表示整个excel
        Workbook workbook = null;
        try {
            //获取excel文件的io流
            InputStream is = file.getInputStream();
            //根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
            if(fileName.endsWith(xls)){
                //2003
                workbook = new HSSFWorkbook(is);
            }else if(fileName.endsWith(xlsx)){
                //2007
                workbook = new XSSFWorkbook(is);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return workbook;
    }
    public static String getCellValue(Cell cell){
        String cellValue = "";
        if(cell == null){
            return cellValue;
        }
        //如果当前单元格内容为日期类型,需要特殊处理
        String dataFormatString = cell.getCellStyle().getDataFormatString();
        if(dataFormatString.equals("m/d/yy")){
            cellValue = new SimpleDateFormat(DATE_FORMAT).format(cell.getDateCellValue());
            return cellValue;
        }
        //把数字当成String来读,避免出现1读成1.0的情况
        if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
            cell.setCellType(Cell.CELL_TYPE_STRING);
        }
        //判断数据的类型
        switch (cell.getCellType()){
            case Cell.CELL_TYPE_NUMERIC: //数字
                cellValue = String.valueOf(cell.getNumericCellValue());
                break;
            case Cell.CELL_TYPE_STRING: //字符串
                cellValue = String.valueOf(cell.getStringCellValue());
                break;
            case Cell.CELL_TYPE_BOOLEAN: //Boolean
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case Cell.CELL_TYPE_FORMULA: //公式
                cellValue = String.valueOf(cell.getCellFormula());
                break;
            case Cell.CELL_TYPE_BLANK: //空值
                cellValue = "";
                break;
            case Cell.CELL_TYPE_ERROR: //故障
                cellValue = "非法字符";
                break;
            default:
                cellValue = "未知类型";
                break;
        }
        return cellValue;
    }
}

2.2.1、创建批量上传控制器

这里使用的dubbo远程调用了接口方法

/**
 * 项目名称:health_parent
 * 描述:预约管理控制器
 *
 * @author zhong
 * @date 2022-06-18 14:50
 */
@RestController
@RequestMapping("/ordersetting")
public class OrderSettingController {
    /**
     * 远程调用预约管理的服务接口
     */
    @Reference
    private OrderSettingService orderSettingService;

    /**
     * 文件上传,实现预约管理的批量导入
     * @param excelFile
     * @return
     */
    @RequestMapping("/upload")
    public Result upload(@RequestParam("excelFile") MultipartFile excelFile){
        try {
            // 1、使用工具类解析上传的数据
            List<String[]> list = POIUtils.readExcel(excelFile);
            // 将读取的表格数据转换为表格预约对象数据
            List<OrderSetting> data = new ArrayList<>();
            // 2、处理解析的数据
            for (String[] strings : list) {
                // 获取到导入数据行的第一个单元格(预约时间)
                String orderSate = strings[0];
                // 获取到导入数据行的第二个单元格(预约姓名)
                String number = strings[1];
                // 将重新获取到的数据添加到预约集合中
                OrderSetting orderSetting = new OrderSetting(new Date(orderSate), Integer.parseInt(number));
                data.add(orderSetting);
            }
            // 2、通过dubbo远程调用服务实现数据批量导入到数据库
            orderSettingService.add(data);

        } catch (IOException e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.IMPORT_ORDERSETTING_FAIL);
        }
        return new Result(true, MessageConstant.IMPORT_ORDERSETTING_SUCCESS);
    }
}

2.2.2、创建批量上传的接口实现类

package com.zcl.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.pojo.OrderSetting;
import com.zcl.dao.OrderSettingDao;
import com.zcl.service.OrderSettingService;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 项目名称:health_parent
 * 描述:预约管理接口实现类
 *
 * @author zhong
 * @date 2022-06-18 15:09
 */
@Service(interfaceClass = OrderSettingService.class)
@Transactional
public class OrderSettingImpl implements OrderSettingService {
    /**
     * 注入保存数据
     */
    @Autowired
    private OrderSettingDao orderSettingDao;

    /**
     * 批量上传业务实现
     * @param data
     */
    @Override
    public void add(List<OrderSetting> data) {
        // 判断集合数据是否为空
        if(data != null && data.size() > 0){
            // 判断当前日期是否已经进行了预约设置
            for (OrderSetting datum : data) {
                // 根据日期查询预约消息
                long count = orderSettingDao.findCountByOrderDate(datum.getOrderDate());
                if(count > 0){
                    // 已进行预约管理,执行更新操作
                    orderSettingDao.editNumberByOrderDate(datum);
                }else{
                    // 添加预约设置
                    orderSettingDao.add(datum);
                }
            }
        }else{

        }
    }
}

2.2.3、创建数据访问层接口和映射文件

package com.zcl.dao;

import com.itheima.pojo.OrderSetting;

import java.util.Date;

/**
 * 项目名称:health_parent
 * 描述:预约管理数据访问层
 *
 * @author zhong
 * @date 2022-06-18 15:13
 */
public interface OrderSettingDao {
    /**
     * 添加预约数据
     * @param orderSetting
     */
    void add(OrderSetting orderSetting);

    /**
     * 修改预约数据
     * @param orderSetting
     */
    void editNumberByOrderDate(OrderSetting orderSetting);

    /**
     * 查询预约数据的总数
     * @param orderDate
     * @return
     */
    long findCountByOrderDate(Date orderDate);
}

数据访问层映射文件编写SQL语句

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zcl.dao.OrderSettingDao">
    <!--添加预约嘻嘻嘻-->
    <insert id="add" parameterType="com.itheima.pojo.OrderSetting">
        insert into t_ordersetting (orderDate,number,reservations)
        values (#{orderDate},#{number},#{reservations});
    </insert>

    <!--根据日期修改预约信息-->
    <update id="editNumberByOrderDate" parameterType="com.itheima.pojo.OrderSetting">
        update t_ordersetting
        set number = #{number}
        where orderDate = #{orderDate}
    </update>

    <!--根据日期查询数据-->
    <select id="findCountByOrderDate" parameterType="date" resultType="java.lang.Long">
        select count(id)
        from t_ordersetting
        where orderDate = #{orderDate}
    </select>
</mapper>

3、批量导入数据测试

在上传模板上制作数据,然后进行导入,先导入新的数据再导入修改后日期不变的数据再次上传数据

到此这篇关于Apache POI操作批量导入MySQL数据库的文章就介绍到这了,更多相关Apache POI操作批量导入MySQL内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!


Tags in this post...

Servers 相关文章推荐
nginx常用命令放入shell脚本详解
Mar 31 Servers
查看nginx配置文件路径和资源文件路径的方法
Mar 31 Servers
Filebeat 采集 Nginx 日志的方法
Mar 31 Servers
解析在浏览器地址栏输入一个URL后发生了什么
Jun 21 Servers
图文详解Nginx版本平滑升级方案
Sep 15 Servers
解决使用了nginx获取IP地址都是127.0.0.1 的问题
Sep 25 Servers
Nginx限流和黑名单配置
May 20 Servers
解决Vmware虚拟机安装centos8报错“Section %Packages Does Not End With %End. Pane Is Dead”
Jun 01 Servers
Win Server2016远程桌面如何允许多用户同时登录
Jun 10 Servers
windows系统安装配置nginx环境
Jun 28 Servers
Windows server 2016服务器基本设置
Aug 14 Servers
修改Nginx配置返回指定content-type的方法
Sep 23 Servers
Ubuntu安装Mysql+启用远程连接的完整过程
Jun 21 #Servers
shell进度条追踪指令执行时间的场景分析
Jun 16 #Servers
Linux服务器离线安装 nginx的详细步骤
Jun 16 #Servers
利用Apache Common将java对象池化的问题
Jun 16 #Servers
Tomcat 与 maven 的安装与使用教程
V Rising 服务器搭建图文教程
安装harbor作为docker镜像仓库的问题
You might like
php获取用户IPv4或IPv6地址的代码
2012/11/15 PHP
浅析php插件 Simple HTML DOM 用DOM方式处理HTML
2013/07/01 PHP
php实现文件编码批量转换
2014/03/10 PHP
PHP pthreads v3使用中的一些坑和注意点分析
2020/02/21 PHP
Chosen 基于jquery的选择框插件使用方法
2012/05/30 Javascript
JQuery页面图片切换和新闻列表滚动效果的具体实现
2013/09/26 Javascript
jquery Tab效果和动态加载的简单实例
2013/12/11 Javascript
javascript针对cookie的基本操作实例详解
2015/11/30 Javascript
无需 Flash 使用 jQuery 复制文字到剪贴板
2016/04/26 Javascript
Node.js+jade抓取博客所有文章生成静态html文件的实例
2017/09/19 Javascript
Three.js利用顶点绘制立方体的方法详解
2017/09/27 Javascript
详解Vue路由History mode模式中页面无法渲染的原因及解决
2017/09/28 Javascript
JavaScript for循环 if判断语句(学习笔记)
2017/10/11 Javascript
react配合antd组件实现的管理系统示例代码
2018/04/24 Javascript
Vue中的$set的使用实例代码
2018/10/08 Javascript
使用p5.js实现动态GIF图片临摹重现
2019/10/23 Javascript
[02:11]完美世界DOTA2联赛10月28日赛事精彩集锦:来吧展示实力强劲
2020/10/29 DOTA
pytorch + visdom 处理简单分类问题的示例
2018/06/04 Python
python爬取网页内容转换为PDF文件
2020/07/28 Python
Python内存管理实例分析
2019/07/10 Python
django url到views参数传递的实例
2019/07/19 Python
简单了解python filter、map、reduce的区别
2020/01/14 Python
TensorBoard 计算图的查看方式
2020/02/15 Python
Python列表切片常用操作实例解析
2020/03/10 Python
python递归调用中的坑:打印有值, 返回却None
2020/03/16 Python
Python闭包及装饰器运行原理解析
2020/06/17 Python
Python如何定义有可选参数的元类
2020/07/31 Python
html5借用repeating-linear-gradient实现一把刻度尺(ruler)
2019/09/09 HTML / CSS
美术专业学生个人自我评价
2013/09/19 职场文书
2014年大学生自我评价
2014/01/19 职场文书
法学毕业生自我鉴定
2014/01/31 职场文书
机械设计及其自动化求职推荐信
2014/02/17 职场文书
廉洁教育学习材料
2014/05/19 职场文书
教师党员个人整改措施
2014/10/27 职场文书
MySQL连接查询你真的学会了吗?
2021/06/02 MySQL
Alexa停服!网站排名将何去何从?目前还没有替代品。
2022/04/15 杂记