Ponieważ jest to bardzo częste pytanie, napisałem
ten artykuł , na którym opiera się ta odpowiedź.
setFirstResult
I setMaxResults
Query
metody
Dla JPA i hibernacji Query
The setFirstResult
metoda jest równoważne OFFSET
, a setMaxResults
sposób jest odpowiednikiem dopuszczalnych:
List<Post> posts = entityManager
.createQuery(
"select p " +
"from Post p " +
"order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
LimitHandler
abstrakcja
Hibernacja LimitHandler
definiuje 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 setFirstResult
i setMaxResults
jest 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 setFirstResult
i setMaxResults
sió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 -setMaxResults
jak zauważył @Rachel w odpowiedzi @skaffman.