Aller au contenu

Semaine 4 : JOUR 3 – SPRING DATA JPA & PERSISTANCE (H2 → JPA → REPOSITORIES)

Formation Java / Spring Boot – Passage à la persistance réelle


Objectifs

À l’issue de cette journée, vous sevez capable de :

Aujourd’hui, votre projet devient une vraie application persistante !


1) Pourquoi une couche de persistance ?

Jusqu’à présent on utilisait souvent des tableaux, des ArrayList, des HashMap.

private final Map<String, Compte> stockage = new HashMap<>();

Limites :

Nous allons connecter le projet à une base PostgreSQL


2) Qu’est-ce que JPA ?

JPA est une spécification Java permettant :

JPA n’est pas un outil concret.
Hibernate est l’implémentation la plus utilisée.

Spring Boot intègre Hibernate automatiquement.


3) Notion clé : ORM

ORM = Object Relational Mapping

Correspondance :

Java Base de données
Classe Table
Objet Ligne
Attribut Colonne
id Clé primaire

4) Configuration H2 (base embarquée)

Dans application.properties :

spring.datasource.url=jdbc:h2:mem:banklite
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update

Avec l’option ddl-auto=update cela permet de :

Console H2 :

http://localhost:8080/h2-console

5) Création d’une entité JPA

Étape 1 – Annoter la classe Compte

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Compte {

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

    private String numero;

    private BigDecimal solde;

    // constructeurs
    // getters
}

6) Héritage JPA – Stratégies possibles

Stratégie Description
SINGLE_TABLE Une seule table
JOINED Une table par classe
TABLE_PER_CLASS Une table par classe concrète

Pour l’apprentissage : utilisez JOINED.


7) Sous-classes

@Entity
public class CompteCourant extends Compte {

    private BigDecimal decouvertAutorise;
}
@Entity
public class CompteEpargne extends Compte {
}

8) Création du Repository JPA

public interface CompteRepository 
        extends JpaRepository<Compte, Long> {

    Optional<Compte> findByNumero(String numero);
}

Aucun code à écrire
Méthodes CRUD générées automatiquement

Méthodes disponibles :


9) Adapter le Service

@Service
public class CompteService {

    private final CompteRepository repository;

    public CompteService(CompteRepository repository) {
        this.repository = repository;
    }

    public List<Compte> listerComptes() {
        return repository.findAll();
    }

    public Compte creerCompte(Compte compte) {
        return repository.save(compte);
    }

    public Compte trouverParNumero(String numero) {
        return repository.findByNumero(numero)
                .orElseThrow(() -> 
                    new IllegalArgumentException("Compte introuvable"));
    }
}

10) Test manuel via API REST

POST :

POST /api/comptes

GET :

GET /api/comptes

Les données persistent désormais en base H2.


11) Comprendre Optional (important)

Optional<Compte>

Évite :

if (compte == null)

Bonne pratique :

repository.findByNumero(numero)
    .orElseThrow(...)

12) Requêtes dérivées Spring Data

Exemple :

List<Compte> findBySoldeGreaterThan(BigDecimal montant);

Spring génère automatiquement la requête SQL.


13) Transactions (introduction simple)

Ajouter :

@Transactional

Sur une méthode service :

@Transactional
public void virer(...) {
}

Garantit :


14) Travaux pratiques – JOUR 17


TP 1 – Migration complète vers JPA

Consignes :

  1. Supprimer l’ancien repository mémoire
  2. Créer l’entité Compte
  3. Créer CompteRepository
  4. Adapter le service
  5. Tester via API

TP 2 – Ajout d’une requête personnalisée

Consignes :


TP 3 – Test transactionnel

Consignes :

  1. Créer un service de virement
  2. Ajouter @Transactional
  3. Simuler une exception après débit
  4. Vérifier que le crédit n’est pas effectué

15) Erreurs fréquentes

  1. Oublier @Entity
  2. Oublier @Id
  3. Ne pas définir de constructeur vide
  4. Confondre id technique et numéro métier
  5. Mettre de la logique métier dans l’entité persistante
  6. Ne pas comprendre Optional
  7. Oublier @Transactional
  8. Mélanger entité et DTO (à venir)
  9. Penser que JPA fait tout
  10. Ignorer la console H2

16) État du projet

BankLite est maintenant :


Synthèse de la journée

Vous savez désormais :

Projet avec un backend professionnel.


Suite…

On abordera :

On entre dans le niveau avancé.

```