在不使用Hibernate一次加载所有结果的情况下迭代结果集的惯用方法是什么?

时间:2013-09-04 12:53:29

标签: java mysql sql hibernate pagination

假设我有一个这样的查询对象:

final SQLQuery query = createQuery(); // org.hibernate.SQLQuery
// HibernateTransaction is just a wrapper around Hibernate's Transaction, Session and
// SessionFactory classes

// the corresponding method:
private SQLQuery createQuery(HibernateTransaction t) {
    final SQLQuery query = t.fullSQLQuery(MY_QUERY_STRING);
    query.addScalar("column1", Hibernate.LONG);
    query.addScalar("column2", Hibernate.LONG);
    query.setResultTransformer(new AliasToBeanResultTransformer(MyDTO.class));
    return query;
}

SQLQuery对象有一个名为iterate()的方法。我的问题是,如果我尝试做这样的事情:

Iterator<MyDTO> iterator = query.iterate();
while(iterator.hasNext()) {
    MyDTO dto = iterator.next();
    // ...
}

我得到一个不支持迭代的异常。如果我使用query.list()方法然后我得到一个List<MyDTO>这很好但是如果我的查询返回一百万行它会变慢并最终耗尽内存。

我的问题是,使用Hibernate只能一次获取一行并且懒洋洋地迭代它们的惯用方法是什么?在我的例子中,我尝试逐行处理表中的数据。

我正在考虑使用聚簇索引,只查询1000行一次,接下来的1000将基于前1000个的最后一个id(所以我基​​本上考虑的是分页)但是我们使用的是MyISAM表而不是支持这个。

2 个答案:

答案 0 :(得分:0)

您可以使用SQLQuery类中的setMaxResults()setFirstResult()方法。它们允许您模拟offsetlimit SQL子句。

例如,如果您希望将rownum = 0的结果加载到rownum = 50,则可以使用setFirstResult(0)setMaxResults(50)等等。

来源:Hibernate Javadocs

答案 1 :(得分:0)

是的,我们可以使用setMaxResults()的{​​{1}}和setFirstResult()方法实现分页,你必须编写类似

的内容
org.hibernate.SQLQuery

和循环如下

// the corresponding method:
private SQLQuery createQuery(HibernateTransaction t,int lowLimit,int pageSize) {
    final SQLQuery query = t.fullSQLQuery(MY_QUERY_STRING);
    query.addScalar("column1", Hibernate.LONG);
    query.addScalar("column2", Hibernate.LONG);
    query.setFirstResult(lowLimit);
    query.setMaxResults(pageSize);
    query.setResultTransformer(new AliasToBeanResultTransformer(MyDTO.class));
    return query;
}

所以这个循环将首先获取10条记录,然后将计数器递增10,这个循环将继续,直到所有记录都没有被提取,因为我不确定结果,因为我没有测试过这段代码但应该工作...