Fermer

juillet 2, 2024

JPA Criteria Api – Un code alternatif aux requêtes SQL brutes

JPA Criteria Api – Un code alternatif aux requêtes SQL brutes


Introduction

JPA est une spécification de mise en veille prolongée qui nous aide à gérer, accéder et conserver les données entre les objets SGBDR et Java. L’une de ses principales fonctionnalités est l’API Criteria, qui est une API prédéfinie et a été introduite dans JPA 2.0. Il définit des requêtes de critères indépendantes de la plate-forme écrites en Java et nous permet d’obtenir le même résultat qu’une requête brute par programmation. Il nous fournit un certain contrôle orienté objet sur les requêtes SQL brutes. En écrivant un critère, vous définissez la clause Where d’une requête pour votre classe de domaine spécifiée.

Composants de base

  • Générateur de critères — Il s’agit d’une classe d’usine obtenue à partir du gestionnaire d’entités pour créer divers objets liés aux requêtes tels que des critèresQuery, des prédicats, etc.
  • CritèresRequête — Il représente la structure de la requête spécifiant la clause « select », la clause « Where » et l’ordre du resultSet.
  • Racine — Ceci représente l’entité sur laquelle la requête fonctionnera, c’est-à-dire la clause « from » d’une requête.
  • Prédicats — Ceci représente la clause « where » de la requête.

Étapes pour créer une requête de critères

  • Créez une instance EntityManagerFactory & EntityManager.
  • Créez une instance CriteriaBuilder à l’aide de la méthode getCriteriaBuilder() de la session.
  • Créez une instance CriteriaQuery à l’aide de la méthode createQuery() de CriteriaBuilder.
  • Une fois que nous avons créé l’instance de critèresQuery, nous devons définir la racine de la requête à l’aide de sa méthode from().
  • Pour obtenir le résultat final, créez une instance de requête à l’aide de la méthode createQuery() de la session en passant la requête de critères comme argument, puis utilisez la méthode query.getResultList() ou query.getResultSet().

Implémentation de la requête de critères JPA

Définir une entité

import lombok.*;
import javax.persistence.*;

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class DemoEmp {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private int id;
private String name;
private int salary;
private int experience;
private String departmentName;
}

Définir le générateur de critères

EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");
EntityManager em = emf.createEntityManager();
CriteriaBuilder criteria = em.getCriteriaBuilder(); 
CriteriaQuery<DemoEmp> cq = criteria.createQuery(DemoEmp .class); 
Root<DemoEmp> root = cq.from(DemoEmp .class); 
cq.select(root); 
Query<DemoEmp> query = em.createQuery(cq);

Le code ci-dessus obtiendra toutes les lignes de l’entité DemoEmp de la base de données.

Nous pouvons également utiliser CriteriaBuilder pour restreindre les résultats de requête en fonction des conditions à l’aide d’expressions.

  • Récupérer les entités dont le salaire est supérieur à 50 000
cq.select(root).where(criteria.gt(root.get("salary"), 50000));
  • Récupérer les entités ayant une expérience entre 2 et 5
cq.select(root).where(criteria.between(root.get("experience"), 2, 5));

Il existe également diverses autres méthodes comme isNull(), isNotNull(), isEmpty(), isNotEmpty(), in(), like(), les méthodes d’agrégation, etc.

Nous pouvons également enchaîner ces expressions pour atteindre la condition souhaitée à l’aide de prédicats.

Predicate greaterThanSalary = criteria.gt(root.get("salary"), 50000);
Predicate experience = criteria.between(root.get("experience"), 2, 5);

Maintenant on peut joindre ces 2 conditions avec soit un « Logique »ET » ou un « logique »OU » basé sur notre exigence.

cq.select(root).where(criteria.or(greaterThanSalary, experience));
cq.select(root).where(criteria.and(greaterThanSalary, experience));

Clause GroupBy et Avoir

L’interface AbstractQuery de l’API Criteria dispose de deux méthodes par groupe() et ayant() qui sont utilisés pour filtrer les données en les regroupant et pour définir respectivement les conditions souhaitées sur les données groupées.

CriteriaQuery<DemoEmp> cq = criteria.createQuery(DemoEmp .class); 
Root<DemoEmp> root = cq.from(DemoEmp .class); 
cq.multiselect(root.get("experience"),criteria.count(root)).groupBy(root.get("experience")); 
List<Object[]> results = em.createQuery(cq).getResultList();

Dans le code ci-dessus, nous regroupons le nombre de DempEmp en fonction de leur expérience.

CriteriaQuery<DemoEmp> cq = criteria.createQuery(DemoEmp .class); 
Root<DemoEmp> root = cq.from(DemoEmp .class); 
cq.multiselect(root.get("experience"),criteria.count(root)).groupBy(root.get("experience")).having(criteria.ge(root.get("experience"), 5));  
List<Object[]> results = em.createQuery(cq).getResultList();

Dans le code ci-dessus, nous regroupons le nombre de DempEmp ayant un expérience soit égal, soit supérieur à 5.

CritèresMises à jour

La fonctionnalité CriteriaUpdates nous permet de mettre à jour plusieurs enregistrements dans la base de données à l’aide de l’API Criteria. Nous pouvons créer une instance CriteriaUpdate à l’aide de la méthode createCriteriaUpdate() de CriteriaBuilder.

Cette interface a un ensemble() méthode qui nous permet de mettre à jour l’enregistrement existant avec la valeur souhaitée. Nous pouvons mettre à jour plusieurs attributs et plusieurs enregistrements simultanément.

CriteriaUpdate<DemoEmp> criteriaUpdate = criteria.createCriteriaUpdate(DemoEmp.class); 
Root<DemoEmp> root = criteriaUpdate.from(DemoEmp.class); 
criteriaUpdate.set("experience", 10); 
criteriaUpdate.set("salary", 1000000); 
criteriaUpdate.where(criteria.equal(root.get("id"), 5))
em.createQuery(criteriaUpdate).executeUpdate();

Le code ci-dessus mettra à jour le expérience attribuer une valeur à dix & salaire attribuer une valeur à 100000 pour le DemoEmp avec identifiant =5

CritèresSupprimer

La fonctionnalité CriteriaDelete nous permet de supprimer plusieurs enregistrements de la base de données à l’aide de l’API Criteria. Nous pouvons créer une instance CriteriaDelete à l’aide de la méthode createCriteriaDelete() de CriteriaBuilder. Nous pouvons supprimer plusieurs enregistrements en fournissant une clause Where pour les restrictions.

CriteriaDelete<DemoEmp> criteriaDelete = criteria.createCriteriaDelete(DemoEmp.class);
Root<DemoEmp> root = criteriaDelete.from(DemoEmp.class); 
criteriaDelete.where(criteria.equal(root.get("departmentName"), "Research")); 
em.createQuery(criteriaDelete).executeUpdate();

Le code ci-dessus supprimera tous les employés du «Recherche » département.

Critères Rejoindre

JPA fournit une interface de jointure pour effectuer des jointures afin de récupérer des données à partir de diverses tables de base de données interconnectées. Nous pouvons également effectuer plusieurs jointures au sein d’une seule requête. Pour comprendre cela en détail, modifions notre entité et ajoutons quelques relations pour pratiquer les jointures.

Entité mise à jour

import lombok.*;
import javax.persistence.*; 
import java.util.List;

@Entity 
@Getter 
@Setter 
@NoArgsConstructor 
@AllArgsConstructor 
@Builder 
@EqualsAndHashCode 
public class DemoEmp { 
@Id 
@GeneratedValue(strategy= GenerationType.AUTO) 
private int id; 
private String name; 
private int salary; 
private int experience; 
private String departmentName;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "demo_emp_project_mapping",
joinColumns = {@JoinColumn(name = "demo_emp_id")},
inverseJoinColumns = {@JoinColumn(name = "project_id")}
)
@JsonBackReference
private List<Project> projects;

@ElementCollection
private List<String> certifications;
}
import lombok.*;
import javax.persistence.*;

@Entity 
@Getter 
@Setter 
@NoArgsConstructor 
@AllArgsConstructor 
@EqualsAndHashCode 
public class Project {
@Id 
@GeneratedValue(strategy= GenerationType.AUTO) 
private int id; 
private String name;

@ManyToMany(mappedBy = "projects")
@JsonBackReference
private List<DemoEmp> employees;
}
CriteriaQuery<DemoEmp> cq = criteria.createQuery(DemoEmp .class); 
Root<DemoEmp> root = cq.from(DemoEmp .class); 
List<Predicate> conditions = new ArrayList();

ListJoin<DemoEmp, String> empCertificationJoin = root.joinList("certifications");
conditions.add(criteria.equal(empCertificationJoin, "XYZ_Certification"));

Join<DemoEmp, Project> empProjectJoin = root.join("projects");
conditions.add(criteria.equal(empProjectJoin.get("id"), 1));

cq.orderBy( criteria.asc(root.get("salary")), criteria.desc(root.get("experience")));
cq.select(root).where(conditions.toArray(new Predicate[]{})).distinct(true);

List<DempEmp> finalOutput = em.createQuery(cq).getResultList;

Le code ci-dessus récupérera tous les salariés ayant «XYZ_Certification » et a travaillé sur le projet avec id « 1« . CriteriaQuery’s « où (conditions.toArray (nouveau prédicat[]{})) » combine tous les prédicats présents dans la liste dans une logique « et« .

Avantages de l’utilisation des requêtes par critères

  • Création de requêtes dynamiques — Code dynamique API agréable, propre et orienté objet
  • Type-Sécurité — Il présente les avantages de Java en matière de sécurité de type.
  • Intégration du métamodèle — Détection d’erreur au moment de la compilation.
  • Prise en charge de la refactorisation — Facile à modifier car il offre une meilleure prise en charge des requêtes dynamiques par rapport à HQL et JPQL.

Conclusion

L’API JPA Criteria Query est une fonctionnalité puissante qui vous permet d’écrire un code propre, orienté objet et de type sécurisé. Les critères CriteriaUpdate et CriteriaDelete introduits dans JPA 2.1 font de l’API JPA Criteria une meilleure solution en fournissant la fonctionnalité de mise à jour et de suppression groupée spécifique à une condition qui manquait dans la version précédente. Criteria Joins nous offre précision, flexibilité et efficacité car nous pouvons définir des conditions complexes pour fusionner des données à l’aide de plusieurs critères et opérateurs logiques. L’utilisation de critères pour les jointures nous aide à ignorer les correspondances inutiles et à réduire la taille de l’ensemble de données, ce qui contribue à améliorer les performances tout en traitant de grands ensembles de données.

VOUS TROUVEZ CECI UTILE ? PARTAGEZ-LE






Source link