Puisque c'est une question très courante, j'ai écrit
cet article , sur lequel cette réponse est basée.
Les setFirstResult
et setMaxResults
Query
méthodes
Pour un JPA et Hibernate Query
, la setFirstResult
méthode est l'équivalent de OFFSET
, et la setMaxResults
méthode est l'équivalent de LIMIT:
List<Post> posts = entityManager
.createQuery(
"select p " +
"from Post p " +
"order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
L' LimitHandler
abstraction
Hibernate LimitHandler
définit la logique de pagination spécifique à la base de données et, comme illustré par le diagramme suivant, Hibernate prend en charge de nombreuses options de pagination spécifiques à la base de données:
Maintenant, selon le système de base de données relationnelle sous-jacent que vous utilisez, la requête JPQL ci-dessus utilisera la syntaxe de pagination appropriée.
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 ?
serveur SQL
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
Oracle
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_ > ?
L'avantage d'utiliser setFirstResult
etsetMaxResults
est qu'Hibernate peut générer la syntaxe de pagination spécifique à la base de données pour toutes les bases de données relationnelles prises en charge.
Et, vous n'êtes pas limité aux requêtes JPQL uniquement. Vous pouvez utiliser la méthode setFirstResult
et setMaxResults
sept pour les requêtes SQL natives.
Requêtes SQL natives
Vous n'avez pas à coder en dur la pagination spécifique à la base de données lorsque vous utilisez des requêtes SQL natives. Hibernate peut ajouter cela à vos requêtes.
Donc, si vous exécutez cette requête SQL sur 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 le transformera comme suit:
SELECT p.id AS id,
p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
Cool, non?
Au-delà de la pagination basée sur SQL
La pagination est bonne lorsque vous pouvez indexer les critères de filtrage et de tri. Si vos exigences de pagination impliquent un filtrage dynamique, c'est une bien meilleure approche que d'utiliser une solution à index inversé, comme ElasticSearch.
Consultez cet article pour plus de détails.
Hibernate-5.0.12
. N'est-ce toujours pas disponible? Il serait très difficile d'obtenir un million d'enregistrements environ, puis d'appliquer le filtresetMaxResults
dessus, comme l'a remarqué @Rachel dans la réponse de @skaffman.