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服务器添加Systemd自定义服务过程解析
Mar 31 Servers
扩展多台相同的Web服务器
Apr 01 Servers
小程序后台PHP版本部署运行 LNMP+WNMP
Apr 01 Servers
Nginx配置Https安全认证的实现
May 26 Servers
centos8安装nginx1.9.1的详细过程
Aug 02 Servers
Shell脚本一键安装Nginx服务自定义Nginx版本
Mar 20 Servers
nginx搭建NFS网络文件系统
Apr 14 Servers
tomcat下部署jenkins的方法
May 06 Servers
配置nginx负载均衡
May 06 Servers
使用 DataAnt 监控 Apache APISIX的原理解析
Jul 07 Servers
Docker安装MySql8并远程访问的实现
Jul 07 Servers
Linux安装Docker详细教程
Jul 07 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中strstr、strrchr、substr、stristr四个函数的区别总结
2014/09/22 PHP
PHP上传图片时判断上传文件是否为可用图片的方法
2016/10/20 PHP
JavaScript 组件之旅(二)编码实现和算法
2009/10/28 Javascript
JS Pro-深入面向对象的程序设计之继承的详解
2013/05/07 Javascript
Javascript实现Array和String互转换的方法
2015/12/21 Javascript
js插件Jcrop自定义截取图片功能
2016/10/14 Javascript
js 博客内容进度插件详解
2017/02/19 Javascript
详解vue组件基础
2018/05/04 Javascript
AngularJS自定义过滤器用法经典实例总结
2018/05/17 Javascript
vue使用Font Awesome的方法步骤
2019/02/26 Javascript
vue使用el-upload上传文件及Feign服务间传递文件的方法
2019/03/15 Javascript
nodejs二进制与Buffer的介绍与使用
2019/07/11 NodeJs
基于JavaScript实现留言板功能
2020/03/16 Javascript
vue-admin-template配置快捷导航的代码(标签导航栏)
2020/09/04 Javascript
javascript实现搜索筛选功能实例代码
2020/11/12 Javascript
Python写的一个简单DNS服务器实例
2014/06/04 Python
从源码解析Python的Flask框架中request对象的用法
2016/06/02 Python
用python写个自动SSH登录远程服务器的小工具(实例)
2017/06/17 Python
Django中的Signal代码详解
2018/02/05 Python
使用python编写监听端
2018/04/12 Python
在Python中使用defaultdict初始化字典以及应用方法
2018/10/31 Python
Django实现网页分页功能
2019/10/31 Python
python wav模块获取采样率 采样点声道量化位数(实例代码)
2020/01/22 Python
美国气象仪器、花园装饰和墙壁艺术商店:Wind & Weather
2019/05/29 全球购物
授权委托书格式
2014/07/31 职场文书
2014年十一国庆节爱国演讲稿
2014/09/23 职场文书
投标承诺函范文
2015/01/21 职场文书
2015年暑期社会实践方案
2015/07/14 职场文书
优秀教师工作总结2015
2015/07/22 职场文书
2015年中学总务处工作总结
2015/07/22 职场文书
2015年重阳节活动主持词
2015/07/30 职场文书
Python list去重且保持原顺序不变的方法
2021/04/03 Python
MySQL安装后默认自带数据库的作用详解
2021/04/27 MySQL
python实现Nao机器人的单目测距
2021/09/04 Python
Python编程根据字典列表相同键的值进行合并
2021/10/05 Python
Java中的Kafka为什么性能这么快及4大核心详析
2022/09/23 Java/Android