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;
  }
  @Override
  public <C, X> Page<C> findAll(
      Specification<T> spec, Class<C> clazz, Selections<T, C, X> selection, Pageable pageable) {
    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<C> query = builder.createQuery(clazz);
    Root<T> root = query.from(getDomainClass());
    Predicate predicate = spec.toPredicate(root, query, builder);

    if (predicate != null) {
      query.where(predicate);
    }
    query.select(builder.construct(clazz, selection.select(root, query, builder)));
    List<Expression<?>> groupBy = query.getGroupList();
    Predicate having = query.getGroupRestriction();
    if (pageable.getSort() != null) {
      query.orderBy(toOrders(pageable.getSort(), root, builder));
    }
    TypedQuery<C> typeQuery = em.createQuery(query);
    return pageable == null
        ? new PageImpl<>(typeQuery.getResultList())
        : readPage(typeQuery, pageable, spec, selection, groupBy, having);
  }