How to calculate the number of rows of JPA 2 criteriaquery in a general JPA Dao?
I am a novice in JPA. To implement a general JPA Dao, I need to find the number of rows in the query result set to realize paging After searching the Internet, I couldn't find a practical way The following code is recommended in many articles:
public <T> Long findCountByCriteria(CriteriaQuery<?> criteria) { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<Long> countCriteria = builder.createQuery(Long.class); Root<?> entityRoot = countCriteria.from(criteria.getResultType()); countCriteria.select(builder.count(entityRoot)); countCriteria.where(criteria.getRestriction()); return em.createQuery(countCriteria).getSingleResult(); }
However, this code does not work when using join Is there a way to calculate the number of rows in the query result set using the JPA criteria API?
Update: This is the code to create the criteriaquery:
CriteriaQuery<T> queryDeFinition = criteriaBuilder.createQuery(this.entityClass); Root<T> root = queryDeFinition.from(this.entityClass);
And you can add some joins to the root until the query is executed:
public Predicate addPredicate(Root<T> root) { Predicate predicate = getEntityManager().getCriteriaBuilder().ge(root.join(Entity_.someList).get("id"),13); return predicate; }
And the generated exceptions are as follows:
Generatedlias1 should be on the entity, and generatedlias0 should be on the association I joined Note that I implemented the join correctly because when I execute a query without a count query, it executes without errors and the join works normally, but it throws an exception when I try to execute a count query
Solution
I did this:
public Long getRowCount(CriteriaQuery criteriaQuery,CriteriaBuilder criteriaBuilder,Root<?> root){ CriteriaQuery<Long> countCriteria = criteriaBuilder.createQuery(Long.class); Root<?> entityRoot = countCriteria.from(root.getJavaType()); entityRoot.alias(root.getAlias()); doJoins(root.getJoins(),entityRoot); countCriteria.select(criteriaBuilder.count(entityRoot)); countCriteria.where(criteriaQuery.getRestriction()); return this.entityManager.createQuery(countCriteria).getSingleResult(); } private void doJoins(Set<? extends Join<?,?>> joins,Root<?> root_){ for(Join<?,?> join: joins){ Join<?,?> joined = root_.join(join.getAttribute().getName(),join.getJoinType()); doJoins(join.getJoins(),joined); } } private void doJoins(Set<? extends Join<?,Join<?,?> root_){ for(Join<?,joined); } }
Of course, you don't need root as an input parameter. You can get it from the condition query,