SPRING DATA

Accéder aux données avec JPA

Ce tutoriel vous guide tout au long du processus de création d’une application qui utilise Spring Data JPA pour stocker et récupérer des données dans une base de données relationnelle.

Ce que vous construirez

Vous allez créer une application qui stocke un utilisateur dans une base de données.

De quoi as-tu besoin?

  • Environ 15 minutes
  • Un éditeur de texte ou IDE préféré
  • Java 11 ou version ultérieure
  • Maven 3.5+

Création du projet avec Spring Initializr

Pour initialiser manuellement le projet :

  1. Accéder à https://start.spring.io/. Ce service récupère toutes les dépendances dont vous avez besoin pour une application et effectue l’essentiel de la configuration pour vous.
  2. Choisissez Maven et la language Java.
  3. Cliquez sur Dépendances et sélectionnez Spring Data JPA puis MySQL Driver.
  4. Cliquez sur Générer.
  5. Télécharger le fichier ZIP résultant, qui est une archive d’une application web configurée.

NB : Si votre IDE dispose de l’intégration Spring Initializr, vous pouvez terminer ce processus à partir de votre IDE.

Nous allons maintenant commencer la phase de développement.

Création du projet avec Spring Initializr

Dans cet exemple, nous allons stockez un utilisateur, chacun annoté en tant qu’entité JPA. La classe Utilisateur est la suivante :

package af.cmr.indyli.gespro.business.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Utilisateur {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;

private String firstName;
private String lastName;

public Utilisateur() {
super();
// TODO Auto-generated constructor stub
}

public Utilisateur(String firstName, String lastName) {
super();
this.firstName = firstName;
this.lastName = lastName;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

@Override
public String toString() {
return "Utilisateur [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";
}
}

Ici vous avez une classe Utilisateur avec trois attributs : id, firstName, et lastName. Vous disposez également de deux constructeurs. Le constructeur par défaut et le constructeur avec des paramètres qui va te permettre de créer des instances à l’Utilisateur enregistrer dans la base de données.

La classe Utilisateur est annoté avec @Entity, indiquant qu’il s’agit d’une entité JPA

La propriété Utilisateur de l’objet est annotée afin que JPA la reconnaisse comme l’ID de l’objet. La propriété est également annotée pour indiquer que l’ID doit être généré automatiquement. @Id et @GeneratedValue

Les deux autres propriétés, firstName et lastName, ne sont pas annotées. On suppose qu’elles sont mappées sur des colonnes partageant les mêmes noms que les propriétés elles-mêmes.

Créer des requêtes simples

Spring Data JPA se concentre sur l’utilisation de JPA pour stocker des données dans une base de données relationnelle. Sa fonctionnalité la plus intéressante est la possibilité de créer automatiquement des implémentations de référentiel, au moment de l’exécution, à partir d’une interface de référentiel.

Pour voir comment cela fonctionne, créez une interface comme le montre la figure suivante :

package af.cmr.indyli.gespro.business.dao;

import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import af.cmr.indyli.gespro.business.entity.Utilisateur;


@Repository
public interface UtilisateurRepository extends CrudRepository<Utilisateur, Long> {

List<Utilisateur> findByLastName(String lastName);

Utilisateur findById(long id);
}

UtilisateurRepository étend l’interface CrudRepository. Le type d’entité et l’ID avec lequel elle fonctionne, la classe Utilisateur ainsi que le type Long, sont spécifiés dans les paramètres génériques sur CrudRepository. En étendant CrudRepositoryUtilisateurRepository hérite de plusieurs méthodes pour travailler avec la classe de persistance qui est Utilisateur, notamment des méthodes pour enregistrer, supprimer et rechercher des entités Utilisateur.

Spring Data JPA vous permet également de définir d’autres méthodes de requête en déclarant leur signature de méthode. 

Par exemple, UtilisateurRepository inclut la méthode findByLastName().

Dans une application Java typique, vous pouvez vous attendre à écrire une classe qui implémente UtilisateurRepository. Cependant, c’est ce qui rend Spring Data JPA si puissant : vous n’avez pas besoin d’écrire une implémentation de l’interface du référentiel. Spring Data JPA crée une implémentation lorsque vous exécutez l’application.

Vous pouvez maintenant câbler cet exemple et voir à quoi il ressemble !

Créer une classe d'application

Spring Initializr crée une classe simple pour l’application. Le  code suivant montre la classe créée par Initializr pour cet exemple.

package af.cmr.indyli.gespro.business.application;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class GesproBusinessApplication {

public static void main(String[] args) {
SpringApplication.run(GesproBusinessApplication.class, args);
}
}

@SpringBootApplication est une annotation pratique qui ajoute tous les éléments suivants :

  • @Configuration: marque la classe comme source de définitions de bean pour le contexte de l’application.
  • @EnableAutoConfiguration : Indique à Spring Boot de commencer à ajouter des bean en fonction des paramètres du classpath, d’autres bean et de divers paramètres de propriété. Par exemple, si spring-web mvc se trouve dans le classpath, cette annotation signale l’application comme une application web et active des comportements clés, tels que la mise en place d’un DispatcherServlet.
  • @ComponentScan : Indique à Spring de rechercher d’autres composants, configurations et services dans le paquet af/cmr/indyli/gespro/business, ce qui lui permet de trouver les contrôleurs.

La méthode main() utilise la méthode SpringApplication.run() de Spring Boot pour lancer une application. Avez-vous remarqué qu’il n’y avait pas une seule ligne de XML ? Il n’y a pas non plus de fichier web.xml. Cette application web est 100% pure Java et vous n’avez pas eu à vous occuper de la configuration d’une quelconque plomberie ou infrastructure.

Vous devez maintenant modifier la classe simple créée par Initializr pour vous. Pour obtenir une sortie (vers la console, dans cet exemple), vous devez configurer un enregistreur. Ensuite, vous devez configurer certaines données et les utiliser pour générer une sortie. La figure suivante montre la classe GesproBusinessApplication terminée.

package af.cmr.indyli.gespro.business.application;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import af.cmr.indyli.gespro.business.dao.UtilisateurRepository;
import af.cmr.indyli.gespro.business.entity.Utilisateur;


@SpringBootApplication
public class GesproBusinessApplication {

private static final Logger log = LoggerFactory.getLogger(GesproBusinessApplication.class);

public static void main(String[] args) {
SpringApplication.run(GesproBusinessApplication.class, args);
}

@Bean
public CommandLineRunner demo(UtilisateurRepository repository) {
  return (args) -> {
    // sauvegarder quelques utilisateurs
    repository.save(new Utilisateur("Jack", "Bauer"));
    repository.save(new Utilisateur("Chloe", "O'Brian"));
    repository.save(new Utilisateur("Kim", "Bauer"));
    repository.save(new Utilisateur("David", "Palmer"));
    repository.save(new Utilisateur("Michelle", "Dessler"));

    // rechercher tous les utilisateurs
    log.info("Utilisateurs trouvés avec findAll():");
    log.info("-------------------------------");

    for (Utilisateur utilisateur : repository.findAll()) {
      log.info(utilisateur.toString());
    }

    log.info("");

    // recherche d'un utilisateur individuel par son ID
    Utilisateur utilisateur = repository.findById(1L);
    log.info("Utilisateur trouvé avec findById(1L):");
    log.info("--------------------------------");
    log.info(utilisateur.toString());

    log.info("");

    // recherche des clients par lastname
    log.info("Utilisateur trouvé avec findByLastName('Bauer'):");
    log.info("--------------------------------------------");
    repository.findByLastName("Bauer").forEach(bauer -> {
      log.info(bauer.toString());
    });
    log.info("");
  };
}
}

La classe GesproBusinessApplication comprend une méthode demo() qui soumet le UtilisateurRepository sujet à quelques tests. Tout d’abord, il récupère le contexte UtilisateurRepository de l’application Spring. Ensuite, il enregistre un objet d’utilisateur, démontrant la méthode save() et configurant certaines données avec lesquelles travailler. Ensuite, il appelle findAll() pour récupérer tous les objets utilisateurs de la base de données. Ensuite, il appelle findById()pour en récupérer un seul Utilisateur par son identifiant. Enfin, il appelle findByLastName() pour rechercher tous les utilisateurs dont le nom de famille est « Bauer ».  La méthode demo() renvoie un bean CommandLineRunner qui exécute automatiquement le code au lancement de l’application.

Toutes nos félicitations ! Vous avez écrit une application simple qui utilise Spring Data JPA pour enregistrer des objets et les récupérer dans une base de données, le tout sans écrire d’implémentation concrète de référentiel.