Poiché questa è una domanda molto comune, ho scritto
questo articolo , su cui si basa questa risposta.
I metodi setFirstResult
esetMaxResults
Query
Per un JPA e Hibernate Query
, il setFirstResult
metodo è l'equivalente di OFFSET
e il setMaxResults
metodo è l'equivalente di LIMIT:
List<Post> posts = entityManager
.createQuery(
"select p " +
"from Post p " +
"order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
L' LimitHandler
astrazione
Hibernate LimitHandler
definisce la logica di impaginazione specifica del database e, come illustrato dal diagramma seguente, Hibernate supporta molte opzioni di impaginazione specifiche del database:
Ora, a seconda del sistema di database relazionale sottostante che si sta utilizzando, la query JPQL precedente utilizzerà la sintassi di impaginazione corretta.
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 ?
server 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
Oracolo
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_ > ?
Il vantaggio di usare setFirstResult
esetMaxResults
è che Hibernate può generare la sintassi di impaginazione specifica del database per qualsiasi database relazionale supportato.
E non sei limitato solo alle query JPQL. È possibile utilizzare il metodo setFirstResult
e setMaxResults
sette per le query SQL native.
Query SQL native
Non è necessario codificare in modo rigido l'impaginazione specifica del database quando si utilizzano query SQL native. Hibernate può aggiungerlo alle tue domande.
Quindi, se stai eseguendo questa query SQL su 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 lo trasformerà come segue:
SELECT p.id AS id,
p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
Bene, vero?
Oltre l'impaginazione basata su SQL
L'impaginazione è buona quando è possibile indicizzare i criteri di filtro e ordinamento. Se i requisiti di impaginazione implicano un filtro dinamico, è un approccio molto migliore l'utilizzo di una soluzione con indice invertito, come ElasticSearch.
Dai un'occhiata a questo articolo per maggiori dettagli.
Hibernate-5.0.12
. Questo non è ancora disponibile? Sarebbe davvero pesante ottenere circa un milione di record e quindi applicare il filtro su disetMaxResults
esso, come notato da @Rachel nella risposta di @skaffman.