最近做的系统功能要求从oracle中批量导出数据,而oracle数据库中体量较大,在200w -2000w范围;
从后端的角度考虑这个功能,首先,是否有必要一次导出几百万的数据?(人为查看这么多数据。。。)
其次,如果真的一次导出200w 系统能否承受住读写压力(内存溢出),包括下载的时间太久(100w模拟数据写入需45s)
第三,导出后的大文件能否正常打开?(Excel07以上最大支持104w行,csv和txt理论没有上限,不过csv基本用excel打开)
基于我的建议和业务的讨论下,交互改为了如下界面:
根据查询行数,如果在10w 以内的,可以选择导出全部,如果>10w,则可以自由选择如 10w-20w 之间的数据,即每次下载的行数不超过10w,写入时间大概在10s内(包含查出数据并映射的时间4.6s),这样既保证系统的稳定,也保证了功能性;
环境:springboot2.0 + mybatis3.4
依赖pom:
<!--excel 导出依赖-->
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
下面贴出Excel导出的代码:
参数说明:
rows:为从数据库中查询出的结果集合,我这里并没有拿实体类作映射,其结构见后面贴的图;
filePathAndName:文件下载路径,返回给前端,打开便直接下载;
file:存于服务端目录的相对路径;
private JsonResult exportExcel( List<Map> rows,String filePathAndName,File file) throws IOException {
XSSFWorkbook workbook = new XSSFWorkbook();
SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(workbook, 100);
Sheet first = sxssfWorkbook.createSheet("sheet1");
Row rowin = first.createRow(0);
Iterator<Map> iterator1 = rows.iterator();
Set sets = new TreeSet();
Map map1 = iterator1.next();
sets = map1.keySet(); // column 集合 即 map 中的key 集合
Iterator iterator2 = sets.iterator();
int i = 0;
while (iterator2.hasNext()) { //填充第一行的 column信息,(set无序 所以保持这里和下面数据填充时的列顺序一致 都在set里)
Cell cell = rowin.createCell(i);
i++;
cell.setCellValue(iterator2.next() + "");
}
Iterator<Map> iterator = rows.iterator();//这个地方不要用上面的iterator,否则会从第二条数据开始写
int row = 0;
while (iterator.hasNext()) {
row++;
Row row1 = first.createRow(row);
Map map = iterator.next();
Set<String> set = map.keySet();
Iterator it = set.iterator();
int n = 0;
while (it.hasNext()) {
Cell cell = row1.createCell(n);
n++;
Object o = map.get(it.next());
cell.setCellValue(o + " "); //此处可以进行类型判断,及格式转换;注意此处值可能有空的时候;
//if (o instanceof Date) {
//SimpleDateFormat sdf = new SimpleDateFormat(pattern);
//cell.setCellValue(sdf.format(o));
// }
}
}
FileOutputStream out = new FileOutputStream(file);
sxssfWorkbook.write(out);
out.close();
return JsonResult.success(filePathAndName); //通用的响应值
}
后面两种格式的见下文! 太多了 容易乱。