Wie andere Antworten sind richtig, aber zu einfach, so zur Vollständigkeit präsentiere ich unten Codeausschnitt, um SELECT COUNT
auf einer ausgefeilten JPA Kriterienabfrage durchzuführen (mit mehrfachen Verbindungen, Fetches, Bedingungen).
Es ist leicht modifiziert 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);
}
}
Ich hoffe, es spart jemand Zeit.
Da IMHO JPA-Kriterien-API ist nicht intuitiv noch gut lesbar.
Das ist, was ich mir gedacht habe, danke. Aber das bedeutet, dass ich nicht die gleiche Abfrage-Instanz für die Abfrage der Anzahl der Ergebnisse und der tatsächlichen Ergebnisse verwenden kann, von denen ich weiß, dass sie analog zu SQL sind, die aber diese API viel mehr OOP-ähnlich machen würde. Nun, zumindest kann ich einige der Prädikate wiederverwenden, denke ich. –
@Barett Wenn es eine ziemlich große Anzahl ist, möchten Sie wahrscheinlich keine Liste von Hunderten oder Tausenden von Entitäten in den Speicher laden, nur um herauszufinden, wie viele es gibt! – Affe
@Barett dies wird bei Seitenumbruch viel verwendet. Daher die Notwendigkeit für eine Gesamtzahl und nur eine Teilmenge der tatsächlichen Zeilen. – gkephorus