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基于域名,端口,不同IP的虚拟主机设置的实现
Mar 31 Servers
提升Nginx性能的一些建议
Mar 31 Servers
nginx的zabbix 5.0安装部署的方法步骤
Jul 16 Servers
Nginx源码编译安装过程记录
Nov 17 Servers
Windows Server 2019 配置远程控制以及管理方法
Apr 28 Servers
Windows server 2012 R2 安装IIS服务器
Apr 29 Servers
IIS服务器中设置HTTP重定向访问HTTPS
Apr 29 Servers
如何Tomcat中使用ipv6地址
May 06 Servers
kubernetes集群搭建Zabbix监控平台的详细过程
Jul 07 Servers
Docker容器harbor私有仓库部署和管理
Aug 05 Servers
ssh服务器拒绝了密码 请再试一次已解决(亲测有效)
Aug 14 Servers
Apache SkyWalking 监控 MySQL Server 实战解析
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
支持oicq头像的留言簿(一)
2006/10/09 PHP
ob_start(),ob_start('ob_gzhandler')使用
2006/12/25 PHP
PHP与C#分别格式化文件大小的代码
2011/05/14 PHP
php隐藏IP地址后两位显示为星号的方法
2014/11/21 PHP
PHP实现全角字符转为半角方法汇总
2015/07/09 PHP
Laravel框架实现的使用smtp发送邮件功能示例
2019/03/12 PHP
2007/12/23更新创意无限,简单实用(javascript log)
2007/12/24 Javascript
JS 实现获取打开一个界面中输入的值
2013/03/19 Javascript
jQuery.lazyload+masonry改良图片瀑布流代码
2014/06/20 Javascript
深入理解JavaScript系列(30):设计模式之外观模式详解
2015/03/03 Javascript
Nodejs如何复制文件
2016/03/09 NodeJs
js实现增加数字显示的环形进度条效果
2017/02/05 Javascript
js自定义弹框插件的封装
2020/08/24 Javascript
vant(ZanUi)结合async-validator实现表单验证的方法
2018/12/06 Javascript
关于vue2强制刷新,解决页面不会重新渲染的问题
2019/10/29 Javascript
JS代码触发事件代码实例
2020/01/02 Javascript
[47:53]DOTA2上海特级锦标赛主赛事日 - 1 败者组第一轮#2COL VS Spirit
2016/03/02 DOTA
[01:16:37]【全国守擂赛】第三周决赛 Dark Knight vs. 一个弱队
2020/05/04 DOTA
Python搭建APNS苹果推送通知推送服务的相关模块使用指南
2016/06/02 Python
Python利用turtle库绘制彩虹代码示例
2017/12/20 Python
python使用xslt提取网页数据的方法
2018/02/23 Python
Python读取本地文件并解析网页元素的方法
2018/05/21 Python
Python遍历文件夹 处理json文件的方法
2019/01/22 Python
Puppeteer使用示例详解
2019/06/20 Python
解决pycharm下os.system执行命令返回有中文乱码的问题
2019/07/07 Python
pandas读取csv文件提示不存在的解决方法及原因分析
2020/04/21 Python
Python基于当前时间批量创建文件
2020/05/07 Python
基于keras中的回调函数用法说明
2020/06/17 Python
CSS3 实现穿梭星空动画
2020/11/13 HTML / CSS
施工安全承诺书
2014/05/22 职场文书
小区门卫的岗位职责
2014/09/26 职场文书
先进党员事迹材料
2014/12/24 职场文书
父亲节活动总结
2015/02/12 职场文书
公司2015年终工作总结
2015/05/26 职场文书
图书借阅制度范本
2015/08/06 职场文书
JavaScript中关于预编译、作用域链和闭包的理解
2021/03/31 Javascript