Spring Data JPA est l’un des modules les plus importants offerts par Spring Boot, qui permet de simplifier l’accès à la couche des données (Persistance).
Grace à ce module, on a principalement trois approches permettant la création des requêtes :
- L’annotation @Query : elle permet d’utiliser des requêtes natives.
- Les méthodes de requêtes dérivées : la requête (Query) est construite à partir de nom de la méthode.
- Les Spécifications : pour le cas des requêtes dynamiques.
Dans cet article on va s’intéresser à la dernière approche.
I. Définition Spring Data JPA
Les Spécifications sont une approche fournie par Spring Boot Data JPA permettant de créer des requêtes dynamiques avec des combinaisons très fluides. Elles fournissent un modèle permettant la séparation des critères de recherche de l’objet effectuant cette recherche. Elles répondent bien au Concept Domain Driven Design.
II. Utilisation Spring Data JPA
Durant la mise en place des solutions, on est toujours face à des besoins de récupération (chercher) des infos avec des critères de recherche dynamiques. ➡ Le résultat dépend des paramètres de recherche fournis lors de l’appel.
Exemple : mise en place d’une api GET permettant de retourner un produit ayant pas mal de champs en termes de modélisation dans la couche persistance (entité).
Avec l’approche par requête on aura la possibilité de créer des requêtes, mais avec un nombre fixe de critères ce qui devient de plus en plus complexe quand le nombre de critères de recherche augmente. Sans oublier les noms des méthodes qui deviennent longs et donc incompréhensibles.
Avec l’annotation @Query, on parle d’une requête SQL ou JPQL fixe, donc un changement de critères signifie un changement de la requête, donc avec un nombre important de critères la requête devient complexe.
Grace aux Spécifications il est possible de répondre à ce besoin tout en garantissant la simplicité, la dynamique ainsi que la lisibilité.
III. Implémentation Spring Data JPA
1. Interface Spécification :
L’implémentation des Spécifications se base sur l’utilisation de l’interface Spécification fourni par Spring :
2. Créer une Spécification :
On a la possibilité de créer non seulement des Spécifications customisées pour les différents critères, mais en plus on a la possibilité d’utiliser les expressions Lambda pour implémenter les Spécifications.
- Création de la classe Spécification :
- Étendre l’interface « JpaSpecificationExecutor » dans l’interface Repository
NB : L’interface Spécification offre des méthodes statiques tel que and(), or(), where() et not() permettant la combinaison des plusieurs spécifications.
3. Queries Dynamiques :
Lors de la mise en place des fonctionnalités de recherche on est face à des demandes de filtres dynamiques, dans ce contexte les spécifications sont efficaces.
- Créer la Classe spécification :
- Implémenter une fonction utilisant la Spécification :
Remarques :
Dans l’exemple illustré dans les captures d’écrans, l’objet User_ est un métamodèle statique de l’entité User
IV. Conclusions
Avant de conclure, il serait plus pertinent de répondre à la question suivante : « Quand est-ce qu’on utilise les Spécifications au lieu des requêtes ? »
L’utilisation d’une approche ou de l’autre se base principalement sur le type de l’application en termes d’entités et de champs de recherche : tout simplement, si l’entité contient peu de champs, la recherche va être simple et lisible avec les requêtes(@Query) ou tout simplement les méthodes de requêtes dérivées (Spring Data JPA), et dans ce contexte l’utilisation des Spécifications complexifie le traitement.
Par contre, si l’entité contient de nombreux champs et que nous avons besoin d’effectuer plusieurs requêtes sur des différents champs, on se retrouve face une complexité importante avec plein des méthodes complexes et incompréhensibles et là on parle d’un cadre ou il est intéressant d’implémenter les spécifications.
Pour conclure sur les Spécifications :
Les spécifications offertes par Spring JPA nous permettent d’implémenter des requêtes réutilisables avec une combinaison fluide.
Les spécifications ne sont pas convenables à tous les cas, elles nécessitent des efforts pour leur mise en place.
Il sera intéressant de réfléchir aux spécifications dès qu’on prévoit un nombre important de requêtes et de champs.