0

Suppose I have a query object like this:

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

The SQLQuery object has a method called iterate(). My problem is that If I try to do something like this:

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

I get an exception that iteration is not supported. If I use the query.list() method then I get a List<MyDTO> which is nice but If my query returns a million rows it gets slow and eventually runs out of memory.

My question is that what is the idiomatic way using Hibernate to only fetch a row at a time and lazily iterate over them? In my example I try to process the data in a table row by row.

I was thinking about using clustered indexes and only query like 1000 rows once and the next 1000 will be based on the last id of the previous 1000 (so basically I was thinking about pagination) but we are using MyISAM tables which are not supporting this .

4

2 回答 2

0

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

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

资料来源:休眠 Javadocs

于 2013-09-04T13:02:50.020 回答
0

setMaxResults()是的,我们可以使用你的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;
}

和循环如下

int pageSize = 10;
int lowLimit = 0;
while(lowLimit != -1) {
    int size;
    List<MyDTO> list = query.list();
    size = list.size();
    //prosess your list here
    processResult(list);    
    if(pageSize != size) {
        lowLimit = -1;  
    } else {
      lowLimit = lowLimit + pageSize;   
    }
}

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

于 2013-09-04T14:04:59.313 回答