问题:如何一次处理(读取)成批的1000条记录,并确保仅当前的1000条记录在内存中?假设我的主键叫'ID',而我的表叫Customer

背景:这不是用于用户分页,而是用于编译有关我的表的统计信息。我的可用内存有限,因此我想一次读取1000条记录中的记录。我只读记录,不会被修改。我已经读到StatelessSession对于这种事情有好处,而且我听说有人在使用ScrollableResults

我尝试过的工作:目前,我正在开发一个定制解决方案,在该解决方案中我实现了Iterable,并且基本上使用setFirstResultsetMaxResults进行了分页。这对我来说似乎很慢,但是它一次可以获取1000条记录。我想知道如何使用ScrollableResults之类的方法更有效地做到这一点。我还不确定为什么我现在的方法这么慢?我正在按ID排序,但是ID是主键,因此该表应该已经被索引了。

如您所知,我一直在阅读有关如何执行此操作的点点滴滴。如果有人可以为我提供完成此操作的完整方法,将不胜感激。我确实知道您必须在FORWARD_ONLY上设置ScrollableResults,并且调用evict(entity)将使一个实体耗尽内存(除非您正在执行二级缓存,但我尚不知道如何检查我是否在或不)。但是我看不到JavaDoc中的任何方法可以一次读取1000条记录。我希望在缺乏可用内存和网络性能较慢之间取得平衡,因此实际上一次不能通过网络发送记录。我在可能的情况下使用Criteria API。感谢您的详细回复。

最佳答案

将实体加载为只读。

对于HQL

Query.setReadOnly( true );


对于标准

Criteria.setReadOnly( true );


http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/readonly.html#readonly-api-querycriteria

无状态会话与State-Session完全不同。


使用无状态会话执行的操作永远不会级联到关联的实例。无状态会话会忽略集合


http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html#batch-statelesssession
使用flash()和clear()清理会话缓存。

session.flush();

session.clear();

Question about Hibernate session.flush()
ScrollableResults应该可以正常工作。

不要忘记加载的每个项目都会占用内存空间,除非您逐出或清除并需要检查它是否确实工作正常。

Mysql J / Connecotr中的ScrollableResults可以伪造,可以加载整行,但是我认为oracle连接器可以正常工作。

Using Hibernate's ScrollableResults to slowly read 90 million records

如果您找到替代方法,则可以考虑使用这种方式

1. Select PrimaryKey of every rows that you will process
2. Chopping them into PK chunk
3. iterate -
   select rows by PK chunk (using in-query)
   process them what you want

09-25 20:49