Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 23

Création d'interfaces Repository avec Spring Data

Recommended resources

Bonjour ! Dans la leçon précédente, nous avons défini nos entités JPA et modélisé leurs relations. Nous avons maintenant un plan détaillé de nos données, mais il nous manque encore les outils pour les manipuler : les sauvegarder, les lire, les mettre à jour ou les supprimer.

Aujourd'hui, nous allons construire le pont entre nos entités et la base de données. L'objectif est de créer des interfaces Repository pour bénéficier des requêtes dérivées de Spring Data. Vous allez découvrir l'un des aspects les plus puissants et productifs de l'écosystème Spring : la capacité du framework à écrire des requêtes SQL à votre place, simplement en se basant sur le nom d'une méthode Java.

Votre expérience avec des ORM comme Eloquent dans Laravel vous sera précieuse. Le principe est similaire : au lieu d'écrire du SQL, vous interagissez avec des méthodes d'objets. Spring Data pousse cette idée encore plus loin en générant automatiquement l'implémentation de ces méthodes.

1. Le Pattern Repository et JpaRepository

Le "Repository" est un Design Pattern qui a pour but de fournir une abstraction sur la couche de persistance des données. Au lieu d'interagir directement avec des gestionnaires d'entités ou d'écrire du SQL, votre code métier (dans les services) dialogue avec une interface de Repository.

Spring Data JPA fournit une implémentation de ce pattern. Pour chaque entité que vous souhaitez manipuler, vous allez créer une interface qui hérite de JpaRepository.

Spring Data avec JPA

Pour commencer, lisons une brève introduction théorique sur la notion de Repository dans Spring Data. Cet article de David Gayerie est clair et concis.

Lisez les deux premières sections : "Notion de repository" et "Spring Data JPA". Concentrez-vous sur la définition du Repository et le rôle de CrudRepository et JpaRepository.

En résumé, pour créer un repository pour notre entité Product (que nous imaginerons avec un id de type Long), il suffit de déclarer une interface comme ceci :

import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product, Long> {
    // La magie opérera ici
}

Le simple fait d'étendre JpaRepository<Product, Long> vous donne accès, sans aucune ligne de code supplémentaire, à un ensemble complet de méthodes CRUD :

  • save(Product entity) : Sauvegarde ou met à jour un produit.
  • findById(Long id) : Trouve un produit par sa clé primaire.
  • findAll() : Récupère tous les produits.
  • deleteById(Long id) : Supprime un produit par sa clé primaire.
  • count() : Compte le nombre total de produits.
  • ... et bien d'autres !

JpaRepository hérite de CrudRepository et y ajoute des fonctionnalités spécifiques à JPA, comme flush() pour synchroniser le contexte de persistance avec la base de données, et des méthodes optimisées pour la pagination, que nous verrons plus tard. Dans la plupart des projets Spring Boot, vous utiliserez directement JpaRepository.

La vidéo suivante montre concrètement la création de cette interface.

Tutoriel Spring Boot | Spring Data JPA | 2023

Regardons comment créer un Repository en pratique. Cette section de la vidéo de chillotech illustre la création de l'interface et explique l'héritage qui nous fournit les méthodes de base.

Regardez l'extrait de 20:24 à 22:44. L'auteur crée une interface ProductRepository. Notez qu'il choisit d'abord PagingAndSortingRepository puis CrudRepository. Comme nous l'avons dit, JpaRepository est un choix encore plus courant qui englobe les fonctionnalités des deux.


2. Les Requêtes Dérivées (Derived Queries)

Disposer des méthodes CRUD de base est utile, mais insuffisant. Que se passe-t-il si nous voulons trouver tous les produits d'une certaine catégorie ? Ou un utilisateur par son adresse e-mail ? C'est ici que la magie des requêtes dérivées entre en jeu.

Spring Data JPA peut "parser" le nom des méthodes que vous déclarez dans votre interface de Repository pour en déduire la requête SQL à exécuter.

La convention de nommage est la clé. Elle suit un format find...By..., read...By..., query...By..., count...By..., ou get...By.... Le mot-clé By agit comme un délimiteur, et tout ce qui suit est interprété comme des critères de recherche basés sur les attributs de votre entité.

Continuons avec la vidéo de chillotech, qui est un excellent cas pratique.

Tutoriel Spring Boot | Spring Data JPA | 2023

Cette partie de la vidéo est le cœur de notre leçon. Elle montre pas à pas comment créer une requête dérivée, la tester, et même la complexifier avec des mots-clés supplémentaires.

Regardez attentivement l'extrait de 35:47 à 45:32. Suivez la démarche de l'auteur : Il définit la méthode findByName(String name) dans le ProductRepository. Il l'utilise dans le service pour implémenter une recherche. Il montre comment Spring génère la requête SELECT ... WHERE name = ?. Il enrichit la méthode avec le mot-clé Containing et OrderBy pour créer findByNameContainingOrderByPriceAsc.


3. Anatomie d'une Requête Dérivée

Comme vous l'avez vu, la structure est très intuitive. Voici quelques exemples pour illustrer la puissance de cette approche.

L'article de David Gayerie que nous avons consulté plus tôt donne des exemples très clairs du JPQL (Java Persistence Query Language) généré en coulisses.

Spring Data avec JPA

Cet extrait de l'article de David Gayerie formalise les règles de nommage et, surtout, montre le JPQL généré. Cela démystifie le processus en le reliant à des concepts que vous connaissez déjà.

Lisez la section "Ajout de méthodes dans une interface de repository". Portez une attention particulière aux exemples de code qui montrent comment le nom de la méthode (getByLogin, findByNameAndEmail) est traduit en requête JPQL.

Le nombre de mots-clés disponibles est impressionnant. Ils vous permettent de construire des requêtes complexes sans écrire une seule ligne de SQL.

Spring Data JPA Derived Query Methods Reference
Ce tableau résume quelques-uns des mots-clés les plus courants pour les requêtes dérivées, avec un exemple de méthode et le JPQL correspondant. C'est un excellent aide-mémoire.

Voici une liste non exhaustive de combinaisons que vous pouvez utiliser :

  • Combiner des critères : And, Or
    • findByFirstnameAndLastname(String firstname, String lastname)
  • Comparaisons : LessThan, GreaterThan, Between, IsNotNull
    • findByPriceLessThan(double price)
    • findByStartDateBetween(LocalDate start, LocalDate end)
  • Correspondance de chaînes : Containing, StartingWith, EndingWith, IgnoreCase
    • findByNameContainingIgnoreCase(String keyword)
  • Appartenance : In, NotIn
    • findByCategoryIn(Collection<String> categories)
  • Tri : OrderBy...Asc / OrderBy...Desc
    • findByCategoryOrderByPriceDesc(String category)
  • Limiter les résultats : findFirst...By..., findTopN...By...
    • findTop5ByOrderByLastUpdateDesc()

Pour plus d'exemples sur ces mots-clés, vous pouvez vous référer à l'article "Advanced Query Techniques in Spring Data JPA" (ressource LINK). Il détaille chacun de ces cas avec des exemples de code clairs.


4. Les Limites de l'Approche et la Suite

Les requêtes dérivées sont extrêmement puissantes pour une grande majorité des cas d'utilisation. Cependant, pour des requêtes très complexes, les noms de méthodes peuvent devenir absurdement longs et difficiles à lire.

Spring Data JPA Derived Query Methods: The Good and the Bad
Cette image illustre parfaitement le problème : la méthode `findByEmailAndPasswordAndDisabledIsFalseAndLockedIsFalse` est fonctionnelle, mais sa longueur la rend peu lisible et difficile à maintenir.

C'est une excellente illustration de la limite de cette approche. Quand la logique de la requête devient trop complexe, il est préférable d'utiliser une méthode plus explicite.


Conclusion

Félicitations ! Vous maîtrisez maintenant l'un des outils les plus productifs de Spring Data. Vous savez comment créer des interfaces qui permettent un accès aux données de manière quasi déclarative.

Points clés à retenir :

  • En étendant JpaRepository, vous obtenez gratuitement toutes les opérations CRUD de base.
  • Spring Data JPA peut générer des requêtes SQL à partir des noms de méthodes dans vos interfaces de repository (requêtes dérivées).
  • La convention de nommage find...By... est la base, et elle peut être enrichie avec des mots-clés comme And, Or, Containing, OrderBy, etc., pour construire des requêtes complexes.
  • Cette approche est très productive mais peut atteindre ses limites en termes de lisibilité pour des requêtes très complexes.

Dans la prochaine leçon, nous aborderons justement la solution à ce problème. Nous apprendrons à écrire des requêtes personnalisées complexes et sécurisées avec JPQL et l'annotation @Query. Cela vous donnera un contrôle total sur vos requêtes lorsque les requêtes dérivées ne suffisent plus.