Hibernate - HQL分页

ili*_*den 19 pagination hibernate hql

这是一个类似于以下问题:HQL - 分页的行标识符

我正在尝试使用HQL实现分页.我有一个PostgreSQL数据库.

int elementsPerBlock = 10;
int page = 2; //offset = 2*10

String sqlQuery = "FROM Messages AS msg " +
                  " LEFT JOIN FETCH msg.commands AS cmd " +   
                  "ORDER BY msg.identifier ASC" ;

Query query = session.createQuery( sqlQuery )
                     .setFirstResult( elementsPerBlock * ( (page-1) +1 ) )
                     .setMaxResults( elementsPerBlock );
Run Code Online (Sandbox Code Playgroud)

会发生什么是Hibernate获取所有消息,并在它们全部加载后返回所需的消息.

因此,Hibernate获取210000个实体而不是返回的30个实体(每个Messages只有2个命令).

有没有办法将开销减少7000倍?

编辑:我尝试添加 .setFetchSize( elementsPerBlock ) .它没有帮助.

编辑2:生成的SQL查询是:

select ... 
from schemaName.messages messages0_ 
left outer join schemaName.send_commands commands1_ 
on messages0_.unique_key=commands1_.message_key 
order by messages0_.unique_identifier ASC
Run Code Online (Sandbox Code Playgroud)

绝对没有LIMIT或OFFSET

Ste*_*ter 15

根据JPA 2.0规范,第3.8.6节"查询执行",

将setMaxResults或setFirstResult应用于涉及对集合进行提取连接的查询的效果未定义.

它因数据库而异,根据我的经验,结果是Hibernate通常在内存中而不是在数据库查询级别进行分页.

我通常所做的是使用单独的查询来获取所需对象的id,并使用fetch join将其传递给查询.


Odr*_*son 7

我正在使用这个解决方案:

/**
 * @param limitPerPage
 * @param page
 * @return
 */
public List<T> searchByPage(int limitPerPage, int page, String entity) {
    String sql = "SELECT t FROM " + entity + " t";
    Query query = em.createQuery(sql)
            .setFirstResult(calculateOffset(page, limitPerPage))
            .setMaxResults(limitPerPage);
    return query.getResultList();
}

/**
 * @param page
 * @return
 */
private int calculateOffset(int page, int limit) {
    return ((limit * page) - limit);
}
Run Code Online (Sandbox Code Playgroud)

欢迎.