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

6

我有一个数据库中的大量行需要创建一个XML文档。我正在使用Hibernate 3。Criteria和Query接口中的基本list()方法看起来很危险:我猜如果我只是迭代它们,它几乎必须将所有记录读入内存。或者有一些懒加载的魔法吗?如果没有,我似乎还有两个选择:从Query(scroll也存在于Criteria中)使用scroll()或iterate()。即使我只想迭代它们,iterate看起来也不是很好: "第一个SQL查询仅返回标识符"。那么我是正确的,我必须使用scroll()吗?


这些东西同样适用于 NHibernate :) - Nic Wise
5个回答

3

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

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

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

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

对于某些类型的事务,无状态会话可能比有状态会话稍微快一点。


1

如果您不需要将对象标记为已处理,则可以简单地使用scroll()并在完成后从会话中清除这些对象。


1

我想做的是以事务方式输出所有结果。我了解您的意思是我应该从部分构建整个大结果集。我能否使用它们来“拼接”我的一致、大结果集,以便我真正从某个时间点获得快照。 - auramo
我不确定你所说的“以事务方式获得所有结果”的意思是什么。 - Paul Croarkin
我的意思是,我的结果集是一个快照,其他客户端在此期间发生的写入/删除操作不会影响它。 - auramo

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();
}

-1

你知道那些批量查询(例如示例中的10、10和5只猫)是否全部在列表中结束(如果我在内存中使用list()查询表并遍历它? 或者当我继续下一批次时(例如第一批10只猫之后的下一批10只猫),Hibernate是否会卸载第一批次? - auramo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接