大数据分页查询分页导出 - wujiuye/miniexcel GitHub Wiki
目的:实现边查询边写入,避免一次将所有数据查询出来而占用太大的内存。
-
getDataObjectClass
:获取记录的类型; -
autoGenerateTitle
:是否需要在创建Sheet
时自动生成标题,一般情况下返回true就好了,除非导出的表格确实不需要标题; -
getNetOutputDataRealSize
:表示接下来要写入的数据的大小; -
getOutputDataWithSheetNumber
:与getNetOutputDataRealSize
需要配合使用。返回接下来实际需要写入的数据;
实现分页查询分页导出依赖的正是getNetOutputDataRealSize
与getOutputDataWithSheetNumber
这两个方法。前者是表示接下来要写入的数据的大小,后者则需要返回接下来实际需要写入的数据。如果getNetOutputDataRealSize
返回0
则表示结束。
ExcelWriterListener
的定义如下:
public interface ExcelWriterListener<T> {
/**
* 出异常时被调用
*/
default void onError(Exception e) {
e.printStackTrace();
}
/**
* 获取输出的数据的类型
*
* @return
*/
Class<T> getDataObjectClass();
/**
* 是否需要自动生成标题输出,使用反射获取范型T的字段名作为标题
*
* @return 标题会被连续的输出到第一行的连续列
*/
boolean autoGenerateTitle();
/**
* 每次刷盘一次完成后,继续写入数据时先调用该方法获取下一次输出的数据真实的总数
*
* @param sn 第几个sheet
* @return 返回0则结束导出
*/
int getNetOutputDataRealSize(int sn);
/**
* 获取本次需要输出的数据
*
* @param sn 第几个sheet
* @param limitStart 上次完成刷盘后的指针位置 (从0开始) (闭区间-包含)
* @param limitEnd limitStart + getOutputDataSizeWithSheetNumber返回的值 (开区间-不包含)
* @return 不运行返回null,否则抛出异常
*/
List<T> getOutputDataWithSheetNumber(int sn, int limitStart, int limitEnd);
}
getOutputDataWithSheetNumber
方法的两个参数limitStart
与limitEnd
是借鉴了分页查询的思想,实现分页查询、写入。
demo如下:
public class TestMain{
/**
* 测试导出
*/
@Test
public void testWrite() {
AbstractExcelWriter excelWriter = AbstractExcelWriter.createExcelWriter("/tmp/miniexcel-test", ExcelFileType.XLSX);
excelWriter.setSheetSize(1000)
.setBrushPageSize(1000)
.setSheetNameFromat("Sheet{sn}");
writer.write(new ExcelWriterListener() {
private Page<DateModel> data;
@Override
public Class<DateModel> getDataObjectClass() {
return DateModel.class;
}
@Override
public boolean autoGenerateTitle() {
return true;
}
@Override
public int getNetOutputDataRealSize(int sn) {
data = 从数据库查询(); // data包含分页信息
data.setPage(date.getPage()+1); // 设置下一页的页码
return data.getRecords.size(); // 获取当前页的数据总数,返回0则结束
}
@Override
public List<DateModel> getOutputDataWithSheetNumber(int sn, int limitStart, int limitEnd) {
// limitStart和limitEnd在本例中没有用到;
return data.getRecords();
}
});
}
}