web-dev-qa-db-fra.com

Comment paginer une requête JPA

J'ai une table de soumission avec des colonnes telles que ID, Name, Code parmi d'autres propriétés. Mon exigence est de rechercher des enregistrements en fonction des propriétés mentionnées et de renvoyer un ensemble paginé.

Ceci est le pseudocode de ce que je recherche:

searchSubmission(searchFilter sf,pageIndex,noOfRecords) {
   query = 'from submisssion where code=sf.code or id=sf.id order by id start_from (pageIndex*noOfRecords) limit noOfRecords'
   return result();
}

Il semble y avoir beaucoup d'options comme CriteriaBuilder, NamedQuery, etc. Quelle est la plus efficace dans cette situation?

14
Tapan Chandra

Pour tous les objets de requête JPA (à l'exception des requêtes SQL natives), vous devez utiliser la pagination via les méthodes setMaxResults (int) et setFirstResult (int). Par exemple:

  return em.createNamedQuery("yourqueryname", YourEntity.class)
      .setMaxResults(noOfRecords)
      .setFirstResult(pageIndex * noOfRecords));
      .getResultList();

JPA effectuera la pagination pour vous.

Les requêtes nommées sont simplement prédéfinies et peuvent être mises en cache, tandis que les autres types sont créés de manière dynamique.
Le choix consiste donc à utiliser JPQL comme suit: 

Query query = em.createQuery("SELECT s FROM Submission s WHERE s.code = :code or s.id = :id ORDER BY s.id", Submission.class);

Ou bien, api CriteriaBuilder pour former une requête similaire:

    CriteriaBuilder qb = em.getCriteriaBuilder();
    CriteriaQuery<Submission> cq = qb.createQuery(Submission.class);

    Root<Submission> root = cq.from(Submission.class);
    cq.where( qb.or( 
        qb.equal(root.get("code"), qb.parameter(String.class, "code")),
        qb.equal(root.get("id"), qb.parameter(Integer.class, "id"))
    ));
    Query query = em.createQuery(cq);

N'oubliez pas de définir les valeurs de paramètre à l'aide de query.setParameter ("id", sf.id) par exemple.

34
Chris

Vous pouvez utiliser Pageable dans la méthode de référentiel

@Repository
public interface StateRepository extends JpaRepository<State, Serializable> {

@Query("select state from State state where state.stateId.stateCode = ?1")
public State findStateByCode(String code, Pageable pageable);

}

Et dans la couche de service, vous pouvez créer l'objet Pageable:

@Autowire
StateRepository stateRepository;

public State findStateServiceByCode(String code, int page, int size) {
    Pageable pageable = new PageRequest(page, size);
    Page<Order> statePage = stateRepository.findStateByCode(code, pageable);
    return statePage.getContent();
}
2
sendon1982

Comme je l'ai expliqué dans cet article , vous pouvez utiliser la pagination JPA pour les requêtes d'entités et le SQL natif.

Pour limiter la taille de la requête ResultSet sous-jacente, l'interface JPA Query fournit la méthode setMaxResults .

Pour naviguer dans la page suivante, vous devez positionner le jeu de résultats à la fin de la dernière page. À cette fin, l'interface JPA Query fournit la méthode setFirstResult .

Utiliser la pagination avec une requête JPQL se présente comme suit:

Liste posts = entityManager .CreateQuery ( "Sélectionnez p" + "À partir du message p" + "À commander par p. ] .setFirstResult (10) .setMaxResults (10) .getResultList ();

L'API de critères est identique car vous devez créer une Query à partir de la CriteriaQuery:

CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Post> cq = qb.createQuery(Post.class);

Root<Post> root = cq.from(Post.class);
cq.orderBy(qb.asc(root.get("createdOn")));

List<Post> posts = em
.createQuery(cq)
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
0
Vlad Mihalcea