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);
  }
 /**
  * Creates a new {@link SimpleJpaRepository} to manage objects of the given {@link
  * JpaEntityInformation}.
  *
  * @param entityInformation
  * @param entityManager
  */
 public GenericRepositoryImpl(
     final JpaEntityInformation<T, ?> entityInformation,
     final EntityManager entityManager,
     final ByExampleSpecification byExampleSpecification,
     final NamedQueryUtil namedQueryUtil) {
   super(entityInformation, entityManager);
   this.entityInformation = entityInformation;
   this.em = entityManager;
   // provider =
   // DefaultPersistenceProvider.fromEntityManager(entityManager);
   // this.springDataRepositoryInterface = springDataRepositoryInterface;
   this.type = entityInformation.getJavaType();
   this.byExampleSpecification = byExampleSpecification;
   this.namedQueryUtil = namedQueryUtil;
   this.byExampleEnhancedSpecification = new ByExampleEnhancedSpecification(entityManager);
 }