这是一个类似于HQL - row identifier for pagination的问题
我正在尝试使用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 );
发生的情况是,Hibernate获取所有消息,并在它们全部加载后返回所需的消息。
因此,Hibernate获取210000个实体,而不是返回30个实体(每个消息恰好有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
绝对没有限制或偏移量
6条答案
按热度按时间egmofgnx1#
根据JPA 2.0 specification,第3.8.6节查询执行,
将setMaxResults或setFirstResult应用于涉及集合上的FETCH联接的查询的效果未定义。
它因数据库而异,根据我的经验,结果是Hibernate通常在内存中执行分页,而不是在数据库查询级别。
我通常使用一个单独的查询来获取所需对象的ID,并通过FETCH连接将其传递到查询中。
o3imoua42#
我正在使用这个解决方案:
欢迎。
2q5ifsrm3#
我们可以通过查询和条件接口来实现分页:
使用查询接口进行分页:
用于分页的查询接口有两种方法。
**1.Query setFirstResult(Int StartPosition):**此方法接受一个整数,表示结果集中的第一行,从第0行开始。
**2.查询setMaxResults(Int MaxResult):**该方法告诉Hibernate检索固定数量的MaxResults对象。结合使用以上两种方法,我们可以在Web或Swing应用程序中构建分页组件。
示例:
条件界面分页:
Criteria接口用于分页有两种方法。
1.条件setFirstResult(Int First StResult):
设置要检索的第一个结果。
2.列表项条件setMaxResults(Int MaxResults):
对要检索的对象数量设置限制。
示例:
bqf10yzr4#
如果您使用HQL创建自己的查询,则查询构建器方法很可能无法解析和更改定制的HQL查询。因此,您应该将
LIMIT ?, ?
语句放在HQL查询的末尾,然后绑定偏移量参数。jmp7cifd5#
由于您没有针对COMMAND实体的某些属性对结果集进行过滤,因此也可以避免SQL JOIN,并为MESSAGE的命令配置延迟抓取。如果没有JOIN,Hibernate将使用数据库的分页能力。
然而,您必须关心N+1个seletcs问题,即避免为每个延迟获取的命令属性执行一次SELECT操作。您可以通过在HibernateMap中设置Batch-Size属性或在Hibernate设置中全局设置Hibernate.Default_Batch_Fetch_Size来避免此问题。
例如:如果您在Hibernate会话中获取了100个Message对象,并将Batch-Size设置为10,则当您第一次调用Message对象的getCommands()时,Hibernate将获取10个不同消息对象的10个命令关联。查询的数量减少到10个加上原始的获取消息的查询。
看看这里:http://java.dzone.com/articles/hibernate-tuning-queries-using?page=0,1作者通过一个简单的例子比较了不同的获取策略
zpjtge226#
我认为你原来的例外是不正确的。
发生的情况是,Hibernate获取所有消息,并在所有消息加载后返回所需的消息。
查询处理过程中发生的情况是,setFirstResult(culateOffset(page,limitPerPage))被转换为偏移量,而setMaxResults(LimitPerPage)被转换为Limit