Поскольку это очень распространенный вопрос, я написал
эту статью , на которой основан этот ответ.
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.