java使用导出百万级别数据?
java1234
共 2383字,需浏览 5分钟
· 2020-11-16
点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据量过多还会常报OOM错误, 这时候调整JVM的配置参数也不是一个好对策(注:jdk在32位系统中支持的内存不能超过2个G,而在64位中没有限制,但是在64位的系统中,性能并不是太好),好在POI3.8版本新出来了一个SXSSFWorkbook对象,它就是用来解决大数据量以及超大数据量的导入导出操作的,但是SXSSFWorkbook只支持.xlsx格式,不支持.xls格式的Excel文件。
public void exportBigDataExcel(ValueDataDto valueDataDto, String path)
throws IOException {
// 最重要的就是使用SXSSFWorkbook,表示流的方式进行操作
// 在内存中保持100行,超过100行将被刷新到磁盘
SXSSFWorkbook wb = new SXSSFWorkbook(100);
Sheet sh = wb.createSheet(); // 建立新的sheet对象
Row row = sh.createRow(0); // 创建第一行对象
// -----------定义表头-----------
Cell cel0 = row.createCell(0);
cel0.setCellValue("1");
Cell cel2 = row.createCell(1);
cel2.setCellValue("2");
Cell cel3 = row.createCell(2);
cel3.setCellValue("3");
Cell cel4 = row.createCell(3);
// ---------------------------
List list = new ArrayList();
// 数据库中存储的数据行
int page_size = 10000;
// 求数据库中待导出数据的行数
int list_count = this.daoUtils.queryListCount(this.valueDataDao
.queryExportSQL(valueDataDto).get("count_sql"));
// 根据行数求数据提取次数
int export_times = list_count % page_size > 0 ? list_count / page_size
+ 1 : list_count / page_size;
// 按次数将数据写入文件
for (int j = 0; j < export_times; j++) {
list = this.valueDataDao.queryPageList(this.valueDataDao
.queryExportSQL(valueDataDto).get("list_sql"), j + 1,
page_size);
int len = list.size() < page_size ? list.size() : page_size;
"white-space:pre"> for (int i = 0; i < len; i++) {
Row row_value = sh.createRow(j * page_size + i + 1);
Cell cel0_value = row_value.createCell(0);
cel0_value.setCellValue(list.get(i).getaa());
Cell cel2_value = row_value.createCell(1);
cel2_value.setCellValue(list.get(i).getaa());
Cell cel3_value = row_value.createCell(2);
cel3_value.setCellValue(list.get(i).getaa_person());
}
list.clear(); // 每次存储len行,用完了将内容清空,以便内存可重复利用
}
FileOutputStream fileOut = new FileOutputStream(path);
wb.write(fileOut);
fileOut.close();
wb.dispose();
}
public static void main(String[] args) throws Exception {
Test3SXXFS tm = new Test3SXXFS();
tm.jdbcex(true);
}
public void jdbcex(boolean isClose) throws InstantiationException, IllegalAccessException,
ClassNotFoundException, SQLException, IOException, InterruptedException {
String xlsFile = "f:/poiSXXFSBigData.xlsx"; //输出文件
//内存中只创建100个对象,写临时文件,当超过100条,就将内存中不用的对象释放。
Workbook wb = new SXSSFWorkbook(100); //关键语句
Sheet sheet = null; //工作表对象
Row nRow = null; //行对象
Cell nCell = null; //列对象
//使用jdbc链接数据库
Class.forName("com.mysql.jdbc.Driver").newInstance();
String url = "jdbc:mysql://localhost:3306/bigdata?characterEncoding=UTF-8";
String user = "root";
String password = "123456";
//获取数据库连接
Connection conn = DriverManager.getConnection(url, user,password);
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
String sql = "select * from hpa_normal_tissue limit 1000000"; //100万测试数据
ResultSet rs = stmt.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
long startTime = System.currentTimeMillis(); //开始时间
System.out.println("strat execute time: " + startTime);
int rowNo = 0; //总行号
int pageRowNo = 0; //页行号
while(rs.next()) {
//打印300000条后切换到下个工作表,可根据需要自行拓展,2百万,3百万...数据一样操作,只要不超过1048576就可以
if(rowNo%300000==0){
System.out.println("Current Sheet:" + rowNo/300000);
sheet = wb.createSheet("我的第"+(rowNo/300000)+"个工作簿");//建立新的sheet对象
sheet = wb.getSheetAt(rowNo/300000); //动态指定当前的工作表
pageRowNo = 0; //每当新建了工作表就将当前工作表的行号重置为0
}
rowNo++;
nRow = sheet.createRow(pageRowNo++); //新建行对象
// 打印每行,每行有6列数据 rsmd.getColumnCount()==6 --- 列属性的个数
for(int j=0;j nCell = nRow.createCell(j);
nCell.setCellValue(rs.getString(j+1));
}
if(rowNo%10000==0){
System.out.println("row no: " + rowNo);
}
// Thread.sleep(1); //休息一下,防止对CPU占用,其实影响不大
}
long finishedTime = System.currentTimeMillis(); //处理完成时间
System.out.println("finished execute time: " + (finishedTime - startTime)/1000 + "m");
FileOutputStream fOut = new FileOutputStream(xlsFile);
wb.write(fOut);
fOut.flush(); //刷新缓冲区
fOut.close();
long stopTime = System.currentTimeMillis(); //写文件时间
System.out.println("write xlsx file time: " + (stopTime - startTime)/1000 + "m");
if(isClose){
this.close(rs, stmt, conn);
}
}
//执行关闭流的操作
private void close(ResultSet rs, Statement stmt, Connection conn ) throws SQLException{
rs.close();
stmt.close();
conn.close();
}
数据库截图:
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:
https://blog.csdn.net/happyljw/article/details/52809244
粉丝福利:实战springboot+CAS单点登录系统视频教程免费领取
???
?长按上方微信二维码 2 秒 即可获取资料
感谢点赞支持下哈
评论
【送书福利】《Java面试八股文:高频面试题与求职攻略一本通》
先来唠唠最近粉丝面试回来跟我聊天,基本上都提到一个点,在面试过程中八股文占比很高(八股文70%、项目20%、10%算法)除了一些搞算法突出的厂除外。其实现在很多厂八股都是逐渐深入的方式来问,所以大家在学习的过程中,针对一些重点的内容,最好深入去学习,不然还是比较难应对这种追问式的问题。最近刚好从一位
Java后端技术
0
盘点一个使用超级鹰识别验证码并自动登录的案例
点击上方“Python共享之家”,进行关注回复“资源”即可获赠Python学习资料今日鸡汤江上几人在,天涯孤棹还。大家好,我是皮皮。一、前言前几天在Python钻石交流群【静惜】问了一个Python实现识别验证码并自动登录的问题,提问截图如下:验证码的截图如下所示:二、实现过程这里大家激烈的探讨,【
IT共享之家
0
Langchain使用 | 模型、提示和解析器、存储
零、LangChain介绍为各种不同基础模型提供统一接口- 帮助管理提示的框架- 一套中心化接口,用于处理长期记忆(参见Memory)、外部数据(参见Indexes)、其他 LLM(参见Chains)以及 LLM 无法处理的任务的其他代理(例如,计算或搜索)。总的来说,有六大核心模块:Models:
Python之王
0
Stability AI开放Stable Diffusion 3 API,在线免费使用
「Stability AI」宣布开放其最新文本到图像生成模型「Stable Diffusion 3」的API接口,供开发者和企业使用。该模型采用创新的多模态扩散转换器架构,在字体、细节还原、提示理解等方面表现优异,评测结果超越了业内其他顶尖系统。与DALL-E 3和Midjourney v6等最先进
IQ前端
0
小美播报|3月IPTV数据排行榜发布!
小美播报3月IPTV数据排行榜:《与凤行》登顶连续剧榜榜首拥有4.05亿家庭用户的中国IPTV平台已经成为国内主流视听平台,IPTV平台数据对视听产业各环节都具有重要意义。截至2024年4月,全国已有29个省级IPTV加入“看中国”,覆盖全国超2.25亿户家庭、辐射近7亿人。点击查看详情湖南广电与马
流媒体网
0
Java项目实战——打造一款股票区间交易盯盘系统
点击上方“Java进阶学习交流”,进行关注后台回复“Java”即可获赠Java学习资料今日鸡汤身无彩凤双飞翼,心有灵犀一点通。一、简介大家好,我是Snowball。今天给大家分享的内容是基于Java编程,实现股票交易相关功能开发,如果读者对股票或金融衍生物交易不太了解,又比较感兴趣的话可自行查询相关
Java进阶学习交流
0
豆瓣9.7,这部Java神作第3版重磅上市!
Java 程序员们开年就有重磅好消息,《Effective Java 中文版(原书第 3 版)》要上市啦!该书的第1版出版于 2001 年,当时就在业界流传开来,受到广泛赞誉。时至今日,已热销近20年,本书第 3 版已是 Java 程序员的必读神书,被誉为“Java 四大名著之一”,甚至连 Java
菜鸟学Python
0
使用 OpenCV 测量物体尺寸
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达你是否曾经遇到过这样的问题:想要知道计算器的精确尺寸,但手头又没有专业的测量工具?别担心,今天我们就来教大家一个简单又实用的方法,通过一张A4纸就能估算出计算器的宽度和高度,精确到毫米哦!该算法的主要思想其实非常简单。请看下面图
小白学视觉
1019