setFirstResult 和 setMaxResults Query 方法
对于 JPA 和 Hibernate Query,setFirstResult 方法等效于 OFFSET,setMaxResults 方法等效于 LIMIT:
List<Post> posts = entityManager
.createQuery(
"select p " +
"from Post p " +
"order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
LimitHandler 抽象
Hibernate LimitHandler 定义了特定于数据库的分页逻辑,如下图所示,Hibernate 支持许多特定于数据库的分页选项:
现在,根据您使用的底层关系数据库系统,上述 JPQL 查询将使用正确的分页语法。
MySQL
SELECT p.id AS id1_0_,
p.created_on AS created_2_0_,
p.title AS title3_0_
FROM post p
ORDER BY p.created_on
LIMIT ?, ?
PostgreSQL
SELECT p.id AS id1_0_,
p.created_on AS created_2_0_,
p.title AS title3_0_
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
SQL 服务器
SELECT p.id AS id1_0_,
p.created_on AS created_on2_0_,
p.title AS title3_0_
FROM post p
ORDER BY p.created_on
OFFSET ? ROWS
FETCH NEXT ? ROWS ONLY
甲骨文
SELECT *
FROM (
SELECT
row_.*, rownum rownum_
FROM (
SELECT
p.id AS id1_0_,
p.created_on AS created_on2_0_,
p.title AS title3_0_
FROM post p
ORDER BY p.created_on
) row_
WHERE rownum <= ?
)
WHERE rownum_ > ?
使用setFirstResult 和setMaxResults 的优势在于Hibernate 可以为任何受支持的关系数据库生成特定于数据库的分页语法。
而且,您不仅限于 JPQL 查询。原生 SQL 查询可以使用setFirstResult 和setMaxResults 方法七。
原生 SQL 查询
使用本机 SQL 查询时,您不必对特定于数据库的分页进行硬编码。 Hibernate 可以将其添加到您的查询中。
所以,如果你在 PostgreSQL 上执行这个 SQL 查询:
List<Tuple> posts = entityManager
.createNativeQuery(
"SELECT " +
" p.id AS id, " +
" p.title AS title " +
"from post p " +
"ORDER BY p.created_on", Tuple.class)
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
Hibernate 会将其转换如下:
SELECT p.id AS id,
p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
很酷,对吧?
超越基于 SQL 的分页
当您可以索引过滤和排序标准时,分页是很好的。如果您的分页要求意味着动态过滤,那么使用倒排索引解决方案(如 ElasticSearch)是一种更好的方法。