Hibernate:避免一次将所有记录读入内存

时间:2008-11-16 16:41:25

标签: java nhibernate hibernate

我在数据库中有大量的行,我需要从中创建XML文档。我正在使用hibernate 3. Criteria和Query接口中的基本list()方法看起来很危险:我认为它几乎必须将所有记录读入内存,即使我只是迭代它们。还是有一些懒惰的装载魔法?如果没有,我似乎还剩下两个选项:使用来自Query的scroll()或iterate()(滚动也出现在Criteria中)。如果我想要最小的SQL往返,则iterate看起来并不那么好:“第一个SQL查询仅返回标识符”。我是对的,我必须使用scroll()吗?

5 个答案:

答案 0 :(得分:3)

尝试将scroll()与此结合使用:

http://docs.jboss.org/hibernate/core/3.3/api/org/hibernate/StatelessSession.html

面向命令的API,用于对数据库执行批量操作。

无状态会话不实现第一级缓存,也不与任何二级缓存交互,也不实现事务性后写或自动脏检查,也不会对关联实例进行级联操作。无状态会话将忽略集合。通过无状态会话执行的操作绕过Hibernate的事件模型和拦截器。由于缺少第一级缓存,无状态会话容易受到数据别名影响。

对于某些类型的事务,无状态会话的执行速度可能比有状态会话略快。

答案 1 :(得分:1)

在Criteria上使用setMaxResults()方法。

Criteria crit = sess.createCriteria(Cat.class);
crit.setMaxResults(maxResults);
crit.setFirstResult(firstResultIndex);
List cats = crit.list();

http://hibernate.org/hib_docs/v3/reference/en/html/querycriteria.html

http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Criteria.html

答案 2 :(得分:1)

如果您不需要按照规定将对象标记为关闭,则可以使用scroll()并在完成对象时逐出对象。

答案 3 :(得分:0)

这是我打算做的事情: 创建一个临时表,其中包含我需要导出的所有行的对象ID:

Insert into BatchTable (ID, Seq) Select (O.ID, Sequence.Next) 
From MyObject O Where ...

在对象的小工作负荷中:

Select Min(B.Seq), Max(B.Seq) From BatchTable;

for (batch = minBatch; batch <= maxBatch; batch += size) {
 beginTransaction();
 results = query("Select O From MyObject O, BatchTable B 
                  Where O.ID = B.ID and (? <= B.Seq AND B.Seq < ?)");

 exportXML(results);
 for (MyObject O : results) {
  O.setProcessed(True);
  O.update();
 }
 commit();
}

答案 4 :(得分:-1)

另外,看看批量提取第19.1.4节和19.1.5应该做什么。 http://www.hibernate.org/hib_docs/v3/reference/en-US/html_single/#queryhql-joins-forms