Excel导入导出

Posted by Wh0ami-hy on December 10, 2023

在项目开发中往往需要使用到数据的导入和导出,导入就是从 Excel 中导入到 DB 中,而导出就是从 DB 中查询数据然后使用 POI 写到 Excel 上。

1. 存在的问题

1、 我遇到的数据量超级大,使用传统的 POI 方式来完成导入导出很明显会内存溢出,并且效率会非常低;

2、 数据量大直接使用select * from tableName肯定不行,一下子查出来 300w 条数据肯定会很慢;

3、 300w 数据导出到 Excel 时肯定不能都写在一个 Sheet 中,这样效率会非常低;估计打开都得几分钟;

4、 300w 数据导出到 Excel 中肯定不能一行一行的导出到 Excel 中。频繁 IO 操作绝对不行;

5、 导入时 300 万数据存储到 DB 如果循环一条条插入也肯定不行;

6、导入时 300w 数据如果使用 Mybatis 的批量插入肯定不行,因为 Mybatis 的批量插入其实就是 SQL 的循环;一样很慢。

2. 解决方案

针对 1 :

其实问题所在就是内存溢出,我们只要使用对上面介绍的 POI 方式即可,主要问题就是原生的 POI 解决起来相当麻烦。

经过查阅资料翻看到阿里的一款 POI 封装工具 EasyExcel,上面问题等到解决;

针对 2:

不能一次性查询出全部数据,我们可以分批进行查询,只不过时多查询几次的问题,况且市面上分页插件很多。此问题好解决。

针对 3:

可以将 300w 条数据写到不同的 Sheet 中,每一个 Sheet 写一百万即可。

针对 4:

不能一行一行的写入到 Excel 上,我们可以将分批查询的数据分批写入到 Excel 中。

针对 5:

导入到 DB 时我们可以将 Excel 中读取的数据存储到集合中,到了一定数量,直接批量插入到 DB 中。

针对 6:

不能使用 Mybatis 的批量插入,我们可以使用 JDBC 的批量插入,配合事务来完成批量插入到 DB。即 Excel 读取分批+JDBC 分批插入+事务。

3. 具体实现

查询大量数据

在查询数据库层面,需要分批进行查询(我使用的是每次查询 20w)

插入大量数据

建立数据库连接

String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "username";
String password = "password";

Connection connection = DriverManager.getConnection(url, username, password);
// 设置connection对象为非自动提交
connection.setAutoCommit(false);

创建一个PreparedStatement对象,并指定插入语句

String insertQuery = "INSERT INTO mytable (column1, column2) VALUES (?, ?)";
PreparedStatement statement = connection.prepareStatement(insertQuery);

循环准备数据并添加到批处理中

for (int i = 0; i < data.size(); i++) {
    statement.setString(1, data.get(i).getColumn1());
    statement.setString(2, data.get(i).getColumn2());
    statement.addBatch();
}

执行批处理操作

int[] result = statement.executeBatch();

提交事务并关闭连接

connection.commit();
connection.close();

本站总访问量