Ponieważ jest to bardzo częste pytanie, napisałem
ten artykuł , na którym opiera się ta odpowiedź.
setFirstResultI setMaxResults Querymetody
Dla JPA i hibernacji QueryThe setFirstResultmetoda jest równoważne OFFSET, a setMaxResultssposób jest odpowiednikiem dopuszczalnych:
List<Post> posts = entityManager
.createQuery(
"select p " +
"from Post p " +
"order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
LimitHandlerabstrakcja
Hibernacja LimitHandlerdefiniuje logikę stronicowania specyficzną dla bazy danych i jak pokazano na poniższym diagramie, Hibernacja obsługuje wiele opcji stronicowania specyficznych dla bazy danych:

Teraz, w zależności od bazowego systemu relacyjnej bazy danych, którego używasz, powyższe zapytanie JPQL będzie używać właściwej składni stronicowania.
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
Wyrocznia
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_ > ?
Zaletą używania setFirstResulti setMaxResultsjest to, że Hibernacja może generować specyficzną dla bazy danych składnię stronicowania dla dowolnych obsługiwanych relacyjnych baz danych.
I nie jesteś ograniczony tylko do zapytań JPQL. Możesz użyć metody setFirstResulti setMaxResultssiódmej do natywnych zapytań SQL.
Natywne zapytania SQL
Podczas korzystania z rodzimych zapytań SQL nie trzeba kodować stronicowania specyficznego dla bazy danych. Hibernacja może dodać to do twoich zapytań.
Jeśli więc wykonujesz to zapytanie SQL na 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();
Hibernacja przekształci go w następujący sposób:
SELECT p.id AS id,
p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
Fajnie, prawda?
Podział na strony poza SQL
Podział na strony jest dobry, gdy można indeksować kryteria filtrowania i sortowania. Jeśli twoje wymagania stronicowania wymagają dynamicznego filtrowania, o wiele lepiej jest zastosować rozwiązanie z indeksem odwróconym, takie jak ElasticSearch.
Sprawdź ten artykuł, aby uzyskać więcej informacji.
Hibernate-5.0.12. Czy to wciąż nie jest dostępne? Byłoby naprawdę ciężko zdobyć około miliona rekordów, a następnie zastosować na nim filtr -setMaxResultsjak zauważył @Rachel w odpowiedzi @skaffman.