Поскольку это очень распространенный вопрос, я написал
эту статью , на которой основан этот ответ.
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
оракул
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.
Проверьте эту статью для более подробной информации.
Hibernate-5.0.12. Это все еще не доступно? Было бы очень тяжело получить около миллиона записей, а затем применить к ним фильтр,setMaxResultsкак заметил @Rachel в ответе @skaffman.