Da dies eine sehr häufige Frage ist, habe ich
diesen Artikel geschrieben , auf dem diese Antwort basiert.
Die setFirstResult
und setMaxResults
Query
Methoden
Für eine JPA und Ruhezustand Query
, das setFirstResult
ist das Äquivalent von Verfahren OFFSET
und das setMaxResults
Verfahren ist das Äquivalent von LIMIT:
List<Post> posts = entityManager
.createQuery(
"select p " +
"from Post p " +
"order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
Die LimitHandler
Abstraktion
Der Ruhezustand LimitHandler
definiert die datenbankspezifische Paginierungslogik. Wie das folgende Diagramm zeigt, unterstützt der Ruhezustand viele datenbankspezifische Paginierungsoptionen:
Abhängig vom zugrunde liegenden relationalen Datenbanksystem, das Sie verwenden, verwendet die obige JPQL-Abfrage nun die richtige Paginierungssyntax.
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
Orakel
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_ > ?
Der Vorteil von setFirstResult
und setMaxResults
besteht darin, dass Hibernate die datenbankspezifische Paginierungssyntax für alle unterstützten relationalen Datenbanken generieren kann.
Sie sind nicht nur auf JPQL-Abfragen beschränkt. Sie können die setFirstResult
und setMaxResults
-Methode sieben für native SQL-Abfragen verwenden.
Native SQL-Abfragen
Sie müssen die datenbankspezifische Paginierung nicht fest codieren, wenn Sie native SQL-Abfragen verwenden. Der Ruhezustand kann dies zu Ihren Abfragen hinzufügen.
Wenn Sie diese SQL-Abfrage unter PostgreSQL ausführen:
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();
Der Ruhezustand wird es wie folgt transformieren:
SELECT p.id AS id,
p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
Cool, oder?
Jenseits der SQL-basierten Paginierung
Die Paginierung ist gut, wenn Sie die Filter- und Sortierkriterien indizieren können. Wenn Ihre Paginierungsanforderungen eine dynamische Filterung implizieren, ist es viel besser, eine Lösung mit invertiertem Index wie ElasticSearch zu verwenden.
Weitere Informationen finden Sie in diesem Artikel .
Hibernate-5.0.12
. Ist das noch nicht verfügbar? Es wäre sehr schwer,setMaxResults
ungefähr eine Million Datensätze zu erhalten und dann den Filter darauf anzuwenden , wie @Rachel in der Antwort von @skaffman bemerkt hat.