Это довольно старый вопрос, но для полноты вот простое дополнение:
В заголовке сказано что-то об «использовании countDistinct», поэтому countDistinct следует упомянуть здесь:
CriteriaBuilder critBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> critQuery = criteriaBuilder.createQuery(Long.class);
Root<Foo> root = critQuery.from(Foo.class);
critQuery.select(critBuilder.countDistinct(root));
int count = entityManager.createQuery(critQuery).getSingleResult().intValue();
Это важно, если вы не хотите считать двойные строки.
Если вы хотите избежать двойных строк в вашем ResultList, вам придется использовать:
CriteriaBuilder critBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> critQuery = criteriaBuilder.createQuery(Long.class);
Root<Foo> root = critQuery.from(Foo.class);
critQuery.select(root).distinct(true);
List<Foo> result = entityManager.createQuery(critQuery).getResultList();