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);
  }