Nombre total de lignes pour la pagination à l’aide de l’API Critères JPA

J’implémente le type de fonctionnalité “Recherche avancée” pour une entité de mon système de telle sorte que l’utilisateur puisse rechercher cette entité en utilisant plusieurs conditions (éq, ne, gt, lt, etc.) sur les atsortingbuts de cette entité. J’utilise l’API Criteria de JPA pour générer dynamicment la requête Criteria, puis utiliser setFirstResult() & setMaxResults() pour prendre en charge la pagination. Tout allait bien jusqu’à ce point, mais maintenant je veux montrer le nombre total de résultats sur la grid de résultats, mais je n’ai pas vu de manière directe d’obtenir le nombre total de requêtes de critères.
Voici à quoi ressemble mon code:

 CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery cQuery = builder.createQuery(Brand.class); Root from = cQuery.from(Brand.class); CriteriaQuery select = cQuery.select(from); . . //Created many predicates and added to **Predicate[] pArray** . . select.where(pArray); // Added orderBy clause TypedQuery typedQuery = em.createQuery(select); typedQuery.setFirstResult(startIndex); typedQuery.setMaxResults(pageSize); List resultList = typedQuery.getResultList(); 

Mon jeu de résultats pourrait être grand, donc je ne veux pas charger mes entités pour count query, alors dites-moi un moyen efficace d’obtenir un nombre total comme la méthode rowCount() sur les critères (je pense que c’est dans les critères d’Hibernate).

Merci Vladimir! J’ai pris votre idée et utilisé une requête de décompte séparée pour utiliser mon tableau de prédicats existant. L’implémentation finale ressemble à ceci:

 CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery cQuery = builder.createQuery(Brand.class); Root from = cQuery.from(Brand.class); CriteriaQuery select = cQuery.select(from); . . //Created many predicates and added to **Predicate[] pArray** . . CriteriaQuery cq = builder.createQuery(Long.class); cq.select(builder.count(cq.from(Brand.class))); // Following line if commented causes [org.hibernate.hql.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.enabled' [select count(generatedAlias0) from xxx.yyy.zzz.Brand as generatedAlias0 where ( generatedAlias1.enabled=:param0 ) and ( lower(generatedAlias1.description) like :param1 )]] em.createQuery(cq); cq.where(pArray); Long count = em.createQuery(cq).getSingleResult(); . . select.where(pArray); . . // Added orderBy clause TypedQuery typedQuery = em.createQuery(select); typedQuery.setFirstResult(startIndex); typedQuery.setMaxResults(pageSize); List resultList = typedQuery.getResultList() 

Bien que cela fonctionne bien mais je ne suis toujours pas sûr de la raison pour laquelle je dois écrire

 em.createQuery(cq); 

pour le faire fonctionner. Une idée?

Pourquoi n’utilisez-vous pas le compte?

 CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery cQuery = builder.createQuery(Long.class); Root from = cQuery.from(Brand.class); CriteriaQuery select = cQuery.select(builder.count(from)); . . //Created many predicates and added to **Predicate[] pArray** . . select.where(pArray); // Added orderBy clause TypedQuery typedQuery = em.createQuery(select); typedQuery.setFirstResult(startIndex); //typedQuery.setMaxResults(pageSize); // here is the size of your query Long result = typedQuery.getSingleResult(); 

Si vous utilisez Hibernate comme votre fournisseur JPA, consultez les projections , en particulier Projections.rowCount() .

Vous devrez peut-être exécuter la requête deux fois, d’abord obtenir le compte puis obtenir les résultats.

Notez que pour JPA simple, vous aurez peut-être besoin d’une autre approche.