hibernate大量数据查询 内存溢出问题

现在项目中需要对数据进行导出,1万条记录。在excel导出过程,查到hibernate查询时候,内存值会有100M的峰值,加上其他业务,就会报内存溢出问题。

hibernate如何做到list查询出来数据,内存峰值能够比较小(实际对象占用只有50M样子),数据需要导出,所以iterator也不适合。

那位大牛知道如何查询内存值保持一定的稳定值,变化不能太大

liuluoqiu
liuluoqiu 我现在是想把数据库中对象读取出来,但是我希望内存增加的只是我所取得对象大小,hibernate的list使得内存增加了一半
8 年多之前 回复

7个回答

个人认为针对具体的问题要根据实际情况选择最适合的工具,楼主说的这种场景其实完全可以用数据库工具来做,没必要非得用Hibernate甚至非得用Java来做,Oracle/MySQL都有非常好用的数据导出工具

liuluoqiu
liuluoqiu 因为页面显示用了ectable控件,根据页面的列来导出excel
8 年多之前 回复

首先你要确定你要导出的版本,我记得jxl导出的03版本的excle只支持2W条数据量的导出.
解决方案有两个:
1.把查询出来的数据分批(分行)导出,比如每50M为一个文件,然后程序再整合成一个文件.
2.查询数据的时候不要得到对象的所有信息.只得到对象的ID.然后通过load来获取对象的所有信息.

liuluoqiu
liuluoqiu 现在导出excel只有一万条,是支持的,因为跟ectable结合起来了,ectable负责生成excel 程序里面需要查询对象的所有数据的
8 年多之前 回复

你可以讲1万条记录分10次查询,每次只查询1000条记录,然后每个excel中只保存1000条记录。将10个excel文件先打成压缩包,然后将压缩包下载,这样应该比较节省内存

fang_fumin
fang_fumin 那不还是一样,你要先将查询的数据保存在文件中,然后再查询,再将数据保存在文件中,当数据量非常大的时候最好分多个文件保存,然后将这些文件打成压缩包下载,会比较快点
8 年多之前 回复
liuluoqiu
liuluoqiu 没有,只是分几次查询,每次读一部分
8 年多之前 回复
fang_fumin
fang_fumin 你有没有先将数据保存在文件中在查询下一次的数据
8 年多之前 回复
liuluoqiu
liuluoqiu 我也尝试分几次查询,但是测试内存变化还是有那么大
8 年多之前 回复

只查需要的字段,不要用对象,这样应该会少很多,调整也比较简单

分批次查询吧,分页思想

liuluoqiu
liuluoqiu List list = criteria.setFirstResult(0).setMaxResults(2000).list(); List list1 = criteria.setFirstResult(2001).setMaxResults(2000).list(); List list2 = criteria.setFirstResult(4001).setMaxResults(2000).list(); List list3 = criteria.setFirstResult(6001).setMaxResults(2000).list(); List list4 = criteria.setFirstResult(8001).setMaxResults(2000).list();
8 年多之前 回复
zyn010101
zyn010101 把你循环5次的代码贴上来看看
8 年多之前 回复
liuluoqiu
liuluoqiu 尝试过每次查询2000条,循环五次,当时记录这之间内存变化,怎么还是一样啊
8 年多之前 回复

如果是导出的话就要用JDBC查询,连这个都要用Hibernate,简直就是滥用框架!

liuluoqiu
liuluoqiu 与ectable绑定了,字段多,如果用jdbc,我需要查询字段往对象里面填写,这样是不是写的不够灵活了
8 年多之前 回复

不知道你的问题解决了没有,可以利用hibernate的无状态session和滚动结果集来操作你说的问题,可以解决哈:
伪代码:

[code="java"]
StatelessSession session=sessionFactory.openStatelessSession();
Transaction t=session.beginTransaction();

ScrollabeResults sResults=session.getNameQuery("hql").scroll(ScrollMode.FORWARD_ONLY);

while(sResults.next()){
//你的代码
}
t.commit();
session.close();
.......
[/code]
滚动结果集不会立即查询,只会返回当前数据库的游标,你需要多少,就会差多少,而且无状态结果集不会使用一级,二级缓存!

cmyx2008love
晓星 你不是查出来,写到xsl文件中么,为什么还有内存的问题哦,你试试就知道了,我也就不解释了!你试试呗!
8 年多之前 回复
liuluoqiu
liuluoqiu 还没有解决呢,我需要把一万条数据都取出来的,这种方式循环取出后,还是蛮大的
8 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问