Hibernate 4 et les fonctions d'agrégat

Comment réaliser des requêtes avec de telles fonctions dans la clause SELECT en Hibernate 4 ? C'est ce que nous vous proposons de voir dans cet article.
Florent TRIPIERMis à jour le 26 Nov 2013

En SQLLangage permettant de communiquer avec une base de données., les fonctions dagrégat sont les fonctions COUNT(), SUM(), MIN(), MAX() et AVG(). Comment réaliser des requêtes avec de telles fonctions dans la clause SELECT en Hibernate 4 ?

Théorie

Si vous nêtes pas familier avec Hibernate 4, reportez-vous préalablement à larticle  ».

Les fonctions dagrégats sont fournies par le CriteriaBuilder. Il suffit donc de passer en paramètre à votre fonction select() non pas un champ ou un Root mais la fonction dagrégat. Vous passez en paramètre à celles-ci les champs concernés.

Exemple

Si je veux compter les commandes :

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<
Long> criteriaQuery = builder.createQuery(Long.class);
Root<
Commande> root = criteriaQuery.from(Commande.class);
criteriaQuery.select(builder.count(root));
TypedQuery<
Long> typedQuery = entityManager.createQuery(criteriaQuery);
Long result = typedQuery.getSingleResult();

ou si je cherche le montant le plus élevé :

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<
Double> criteriaQuery = builder.createQuery(Double.class);
Root<
Commande> root = criteriaQuery.from(Commande.class);
criteriaQuery.select(builder.max(root.get(Commande_.total)));
TypedQuery<
Double> typedQuery = entityManager.createQuery(criteriaQuery);
List<
Double> result = typedQuery.getResultList();

ou encore si je veux connaître le panier moyen :

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<
Double> criteriaQuery = builder.createQuery(Double.class);
Root<
Commande> root = criteriaQuery.from(Commande.class);
criteriaQuery.select(builder.avg(root.get(Commande_.total)));
TypedQuery<
Double> typedQuery = entityManager.createQuery(criteriaQuery);
List<
Double> result = typedQuery.getResultList();

Attention ! Noubliez pas de modifier le type de votre CriteriaQuery et de votre TypedQuery en fonction de ce que vous voulez ramener. 

Remarque : si votre clause SELECT contient un COUNT() et rien dautre, et seulement dans ce cas là, vous pouvez appeler la fonction getSingleResult() à la place de getResultList(). Pourquoi pas le reste du temps ? Parce que getSingleResult() propage une exception lorsque la requête ramène un nombre de résultat différent de 1 (zéro compris). Or COUNT() ramène forcément un résultat puisque sil ne trouve rien il renvoie 0, alors que SUM() par exemple est susceptible de retourner NULL.