Методы 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 Server
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
Oracle
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. Вы можете использовать седьмой метод setFirstResult
и setMaxResults
для собственных запросов SQL.
Собственные запросы SQL
Вам не нужно жестко кодировать разбиение на страницы для конкретной базы данных при использовании собственных SQL-запросов. Hibernate может добавить это к вашим запросам.
Итак, если вы выполняете этот SQL-запрос в PostgreSQL:
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.
person
Vlad Mihalcea
schedule
25.02.2020
Hibernate-5.0.12
. Это все еще недоступно? Было бы очень сложно получить миллион или около того записей, а затем применить к ним фильтр -setMaxResults
поверх него, как заметил @Rachel в ответе @skaffman. - person Rajeev Ranjan   schedule 23.10.2017