Fonctions de regroupement et d'agrégation

Vous avez déjà compris comment faire des requêtes simples à l'API Criteria. Voyons comment faire des requêtes plus complexes.

Par exemple, nous voulons écrire une requête pour déterminer le nombre d'employés dans une entreprise. Voici à quoi cela ressemblera dans HQL :

select count(*) from Employee

Et comme ceci sur l'API Criteria :

CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));

Le code Java complet ressemblera à ceci :

CriteriaBuilder builder = session.getCriteriaBuilder();

CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));

Query<Long> query = session.createQuery(critQuery);
Long count = query.getSingleResult();

Et c'est pareil avec HQL :

String hqlQuery = "select count(*) from Employee";

Query<Long> query = session.createQuery(hqlQuery);
Long count = query.getSingleResult();

Essayons maintenant de calculer le salaire moyen dans l'entreprise. La requête HQL ressemblera à ceci :

select avg(salary) from Employee

Et comme ceci sur l'API Criteria :

CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));

Le code Java complet ressemblera à ceci :

CriteriaBuilder builder = session.getCriteriaBuilder();

CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));

Query<Double> query = session.createQuery(critQuery);
Double avgSalary = query.getSingleResult();

Mise à jour des critères

Modifier une table est aussi simple que d'en extraire des données. Pour ce faire, CriteriaBuilder a une méthode spéciale - createCriteriaUpdate() , qui crée un objetMise à jour des critères<T>Le qui met à jour les entités dans la base de données.

Augmentons le salaire des employés qui reçoivent moins de 10 mille. Voici à quoi ressemblerait cette requête HQL :

update Employee set salary = salary+20000 where salary<=10000

Et voici à quoi cela ressemblera sur l'API Criteria :

CriteriaUpdate<Employee> criteriaUpdate = builder.createCriteriaUpdate(Employee.class);
Root<Employee> root = criteriaUpdate.from(Employee.class);
criteriaUpdate.set("salary", "salary+20000");
criteriaUpdate.where(builder.lt(root.get("salary"), 10000));

Transaction transaction = session.beginTransaction();
session.createQuery(criteriaUpdate).executeUpdate();
transaction.commit();

CritèresSupprimer

Et supprimer des enregistrements est encore plus facile que de les modifier. Pour ce faire, il existe une méthode spéciale createCriteriaDelete() , qui crée un objetCritèresSupprimer<T>.

Coupons tous les employés qui n'ont aucune valeur : leur salaire est inférieur à 10 mille. Voici à quoi ressemblerait cette requête HQL :

delete from Employee where salary<=10000

Et voici à quoi cela ressemblera sur l'API Criteria :

CriteriaDelete<Employee> criteriaDelete = builder.createCriteriaDelete(Employee.class);
Root<Employee> root = criteriaDelete.from(Employee.class);
criteriaDelete.where(builder.lt(root.get("salary"), 10000));

Transaction transaction = session.beginTransaction();
session.createQuery(criteriaDelete).executeUpdate();
transaction.commit();

Avantages de l'API Criteria

Alors, quel est l'avantage de l'API Criteria ? Les requêtes sont lourdes, HQL sera certainement plus compact.

Premièrement, les requêtes HQL ne sont pas si courtes si vous devez leur transmettre des paramètres. Comparer:

Nous considérons le nombre d'employés avec un salaire inférieur à 10 000
HQL
String hqlQuery = "from Employee where salary < :sal";
Query<Employee> query = session.createQuery(hqlQuery);
query.setParametr("sal", 10000);
List<Employee> results = query.getResultList();
API de critères
CriteriaBuilder builder = session.getCriteriaBuilder();
critQuery.select(critQuery.from(Employee.class)).where(builder.lt(root.get("salary"), 10000));
Query<Employee> query = session.createQuery(critQuery);
List<Employee> results = query.getResultList();

Deuxièmement, il arrive très souvent qu'une requête doive être construite dynamiquement. Par exemple, vous avez une page Web filtrant les employés, les appartements et tout. Et si un paramètre n'est pas important pour l'utilisateur, il ne l'indique tout simplement pas. En conséquence, null est transmis au serveur à la place.

Voici votre tâche : sélectionner des employés avec une certaine profession (occupation), un salaire (salaire) et une année d'emploi (ANNÉE (join_date)). Mais si une valeur de paramètre est nulle, ne l'utilisez pas dans le filtre.

Ensuite, la requête HQL ressemblera à ceci :

from Employee
where (occupation = :ocp)
   	and (salary = :sal)
   	and ( YEAR(join_date) = :jny)

Mais cela ne fonctionnera pas correctement, puisque nous voulons que si le paramètre "jny" était nul, alors la requête ressemblerait à ceci :

from Employee
where (occupation = :ocp)
   	and (salary = :sal)

Nous pouvons essayer de réécrire la requête en vérifiant le paramètre pour null, nous obtiendrons alors quelque chose comme ceci :

from Employee
where (occupation = :ocp or :ocp is null)
   	and (salary = :sal or :sal is null)
   	and ( YEAR(join_date)= :jny or :jny is null)

Vous voyez comment la réalité devient plus compliquée ? La réalité est souvent comme ça :)

Mais le filtre peut être encore plus compliqué. Que diriez-vous de rechercher des utilisateurs dont les tâches contiennent le mot "acheter" ? Ou les utilisateurs qui ont des tâches en retard ?

from Employee
where (occupation = :ocp)
   	and (salary = :sal)
   	and (YEAR(join_date) = :jny)
   	and (tasks.name like '%buy%')
   	and (tasks.deadline < curdate())

Si vous écrivez ou est null quelque part dans une telle requête , cela n'annulera pas la jointure entre les tables.

Ainsi, en pratique, lorsque vous effectuez un filtrage complexe sur les champs de plusieurs tables, l'API Criteria peut simplement vous aider. Alors ça va.

Plus de détails peuvent être trouvés dans la documentation officielle .