一切福田,不離方寸,從心而覓,感無不通。

通过Mybatis的流式查询ResultHandler解决超大Excel导出内存溢出问题

在项目开发过程导出Excel为常用功能,之前的一篇Java导出超大Excel文件,防止内存溢出已经解决了Excel写入层面时的内存问题,但数据库查询层面,仍存在由于默认的mybatis查询是将所有数据都查询到本地内存,因此仍有可能会导致内存溢出,因此本文再详细介绍记录通过mybatis的ResultHander进行流式查询读取来完全解决excel的大量数据导出内存溢出问题。

一.先批量插入测试数据

1.建表,包含2个字段username,age

 

2.UserMapper.xml

 

3.UserMapper.java

 

4.UserService.java & UserServiceImpl.java

 

在这里插入图片描述

5.UserController.java中编写测试代码,写入100万行数据

 

二、ResultHandler流式查询导出

ResultHandler接口可以用于进行流式查询(即一行一行从数据库中读取处理,因此不会占用本地内存),本文的核心就是通过调用mapper的方法,传入一个ResultHandler,然后在实现的方法中读取数据,然后一行一行处理。

1.在UserMapper.xml中配置

其中的resultSetType为FORWARD_ONLY,fetchSize为-2147483648

 

2.UserMapper.java中编写方法

 

重要注意点:要满足流式查询,需要方法返回值为void,并且方法中有ResultHandler类型的参数。在mybatis源码中的MapperMethod.java中也能看到对应的代码判断如下: 在这里插入图片描述

3.自定义一个ExcelResultHandler,提供给所有导出的代码共用

此ResultHandler实现了excel的导出,并遍历mapper查询数据,一行一行写入excel,节省内存,可以在导出的业务代码进行使用,具有通用性,只需要new出对象然后调用相应的方法。

 

4.在UserServiceImpl实现类中进行ExcelResultHandler的调用并写入excel,如下:

 

说明: UserServiceImpl类的导出代码中,只需要new一个ExcelResultHandler,然后实现其抽象方法tryFetchDataAndWriteToExcel(),在tryFetchDataAndWriteToExcel方法中进行mapper的方法调用,传递一个ResultHander对象,如上面代码中的userMapper.export(this), new完ExcelResultHandler对象时,导出还没有开始,执行handler.startExportExcel()才进行真正的导出功能,先拿到输出流,然后设置好excel的表头,并写入表头,然后调用tryFetchDataAndWriteToExcel方法,在tryFetchDataAndWriteToExcel方法中会调用mybatis的mapper的方法,在mybatis的mapper的方法中遍历所有的数据,然后一行一行写入excel,最终关闭资源流等,如下:`

 

4.测试结果截图如下:

输入http://localhost:8080/test/user/export进行导出测试 在这里插入图片描述 在这里插入图片描述

三、源码demo下载

详细源码附件如下:可直接下载进行测试

github: github.com/jxlhljh/spr… gitee: gitee.com/jxlhljh/spr…

 

作者:冰之杍
链接:https://juejin.cn/post/7012156305783652383
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。