private <C, X> Subquery<?> createCountSubQuery( Root<T> root, CriteriaQuery<Long> countQuery, Selections<T, C, X> selection, CriteriaBuilder builder, Specification<T> spec, List<Expression<?>> groupBy, Predicate having) { Subquery<?> subquery = countQuery.subquery(entityInformation.getIdType()); Root subRoot = subquery.from(entityInformation.getJavaType()); Expression[] select = selection.select(subRoot, (AbstractQuery<C>) subquery, builder); subquery.select(select[0]); selection.join(subRoot, builder); Predicate predicate = builder.equal( subRoot.get(entityInformation.getIdAttribute()), root.get(entityInformation.getIdAttribute())); if (predicate != null) { subquery.where(predicate); } if (groupBy != null) { subquery.groupBy(groupBy); } if (having != null) { subquery.having(having); } return subquery; }
private <C, X> TypedQuery<Long> getCountQuery( Specification<T> spec, Selections<T, C, X> selection, List<Expression<?>> groupBy, Predicate having) { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<Long> countQuery = builder.createQuery(Long.class); Root<T> root = countQuery.from(getDomainClass()); Subquery<?> subquery = createCountSubQuery(root, countQuery, selection, builder, spec, groupBy, having); Path<?> path = root.get(entityInformation.getIdAttribute()); countQuery.select(builder.countDistinct(path)).where(builder.exists(subquery)); return em.createQuery(countQuery); }