java - parametros - jpql
Recuento total de filas para la paginaciĆ³n utilizando API de criterios JPA (3)
Estoy implementando el tipo de funcionalidad de "búsqueda avanzada" para una entidad en mi sistema, de modo que el usuario pueda buscar esa entidad usando múltiples condiciones (eq, ne, gt, lt, etc.) en los atributos de esta entidad. Estoy utilizando la API Criteria de JPA para generar dinámicamente la consulta Criteria y luego usar setFirstResult()
y setMaxResults()
para admitir la paginación. Todo estaba bien hasta este punto, pero ahora quiero mostrar el número total de resultados en la grilla de resultados, pero no veo una manera directa de obtener el conteo total de la consulta de Criteria.
Así es como mi código se ve así:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Brand> cQuery = builder.createQuery(Brand.class);
Root<Brand> from = cQuery.from(Brand.class);
CriteriaQuery<Brand> 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();
Mi conjunto de resultados podría ser grande, así que no quiero cargar mis entidades para la consulta de recuento, así que dígame la forma eficiente de obtener el recuento total como método rowCount()
en Criteria (creo que está en los Criterios de Hibernate).
¿Por qué no solo usas el conteo?
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Long> cQuery = builder.createQuery(Long.class);
Root<Brand> from = cQuery.from(Brand.class);
CriteriaQuery<Long> select = cQuery.select(builder.count(from));
.
.
//Created many predicates and added to **Predicate[] pArray**
.
.
select.where(pArray);
// Added orderBy clause
TypedQuery<Long> typedQuery = em.createQuery(select);
typedQuery.setFirstResult(startIndex);
//typedQuery.setMaxResults(pageSize);
// here is the size of your query
Long result = typedQuery.getSingleResult();
Gracias Vladimir! Tomé su idea y usé una consulta de recuento separada para usar mi matriz existente de predicados. La implementación final se ve así:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Brand> cQuery = builder.createQuery(Brand.class);
Root<Brand> from = cQuery.from(Brand.class);
CriteriaQuery<Brand> select = cQuery.select(from);
.
.
//Created many predicates and added to **Predicate[] pArray**
.
.
CriteriaQuery<Long> 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()
Aunque esto está funcionando bien, pero aún no estoy seguro de por qué tengo que escribir
em.createQuery(cq);
para que funcione ¿Alguna idea?
Si está utilizando Hibernate como proveedor de JPA, eche un vistazo a las projections , especialmente Projections.rowCount()
.
Sin embargo, es posible que deba ejecutar la consulta dos veces, primero obtenga el recuento y luego obtenga los resultados.
Tenga en cuenta que para JPA simple puede necesitar algún otro enfoque.