réponses Comme les autres sont corrects, mais trop simple, donc pour l'exhaustivité je présente ci-dessous l'extrait de code pour effectuer SELECT COUNT
sur un sophistiqué Requête de critères JPA (avec plusieurs jointures, extractions, conditions).
Il est légèrement modifié this answer.
public <T> long count(final CriteriaBuilder cb, final CriteriaQuery<T> selectQuery,
Root<T> root) {
CriteriaQuery<Long> query = createCountQuery(cb, selectQuery, root);
return this.entityManager.createQuery(query).getSingleResult();
}
private <T> CriteriaQuery<Long> createCountQuery(final CriteriaBuilder cb,
final CriteriaQuery<T> criteria, final Root<T> root) {
final CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
final Root<T> countRoot = countQuery.from(criteria.getResultType());
doJoins(root.getJoins(), countRoot);
doJoinsOnFetches(root.getFetches(), countRoot);
countQuery.select(cb.count(countRoot));
countQuery.where(criteria.getRestriction());
countRoot.alias(root.getAlias());
return countQuery.distinct(criteria.isDistinct());
}
@SuppressWarnings("unchecked")
private void doJoinsOnFetches(Set<? extends Fetch<?, ?>> joins, Root<?> root) {
doJoins((Set<? extends Join<?, ?>>) joins, root);
}
private void doJoins(Set<? extends Join<?, ?>> joins, Root<?> root) {
for (Join<?, ?> join : joins) {
Join<?, ?> joined = root.join(join.getAttribute().getName(), join.getJoinType());
joined.alias(join.getAlias());
doJoins(join.getJoins(), joined);
}
}
private void doJoins(Set<? extends Join<?, ?>> joins, Join<?, ?> root) {
for (Join<?, ?> join : joins) {
Join<?, ?> joined = root.join(join.getAttribute().getName(), join.getJoinType());
joined.alias(join.getAlias());
doJoins(join.getJoins(), joined);
}
}
Espérons que cela fasse gagner du temps à quelqu'un. Parce que l'API IMHO JPA Criteria n'est pas intuitive ni assez lisible.
C'est ce que je me suis figuré, merci. Mais cela signifie que je ne peux pas utiliser la même instance de requête pour rechercher le nombre de résultats et les résultats réels qui, je le sais, sont analogues à SQL, mais qui rendraient cette API beaucoup plus semblable à la POO. Eh bien, au moins je peux réutiliser certains des prédicats, je suppose. –
@Barett Si c'est un nombre plutôt important, vous ne voulez probablement pas charger une liste de centaines ou de milliers d'entités en mémoire juste pour savoir combien il y en a! – Affe
@Barett ceci est beaucoup utilisé en cas de pagination. D'où la nécessité d'un nombre total et seulement un sous-ensemble des lignes réelles. – gkephorus