Aller au contenu principal

Chapitre 3: Migration de Schéma avec Flyway

Introduction​

Avez-vous déjà vécu cette situation?

"Attends, tu as exécuté quel script SQL en production?"
"Celui avec les nouvelles colonnes... je crois?"
"Mais il y avait 3 versions! V1, V2 ou V2_final_final?"
💀

Flyway résout ce problème en versionnant votre schéma de base de données comme vous versionnez votre code.


🎯 Objectifs du Chapitre​

À la fin de ce chapitre, vous saurez:

  1. ✅ Pourquoi Flyway est essentiel pour la production
  2. ✅ Installer et configurer Flyway avec Spring Boot
  3. ✅ Créer des scripts de migration
  4. ✅ Comprendre la convention de nommage
  5. ✅ Gérer les migrations répétables
  6. ✅ Résoudre les problèmes courants

1. Pourquoi Versionner le Schéma?​

Le Problème​

Problèmes:

  • On ne sait pas quel script a été exécuté
  • Pas de trace de l'historique
  • Risque d'oublier une migration
  • Impossible de reproduire l'environnement

La Solution: Flyway​

Avantages:

  • ✅ Historique complet des migrations
  • ✅ Exécution automatique au démarrage
  • ✅ Identique sur tous les environnements
  • ✅ Impossible d'oublier une migration

2. Installation​

Dépendance Maven​

<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>

<!-- Pour PostgreSQL, ajoutez aussi: -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
</dependency>

Avec Spring Boot​

C'est tout! Spring Boot auto-configure Flyway automatiquement.

# application.properties
spring.flyway.enabled=true # Par défaut: true si Flyway est dans le classpath

3. Structure des Fichiers​

Emplacement par Défaut​

src/
└── main/
└── resources/
└── db/
└── migration/
├── V1__create_users_table.sql
├── V2__add_email_column.sql
├── V3__create_orders_table.sql
└── V4__add_index_on_email.sql

Convention de Nommage​

V{version}__{description}.sql
│ │ │
│ │ └── Description (underscores = espaces)
│ └── Numéro de version (1, 2, 2.1, etc.)
└── Préfixe "V" (Versioned migration)

Exemples valides:

V1__create_users.sql
V2__add_email_to_users.sql
V2.1__add_phone_number.sql
V10__create_products.sql
V100__final_cleanup.sql

Exemples invalides:

V1_create_users.sql       ❌ Un seul underscore
v1__create_users.sql ❌ Minuscule
1__create_users.sql ❌ Pas de préfixe V
V1__create users.sql ❌ Espaces dans le nom

4. Créer des Migrations​

Migration 1: Créer une Table​

-- V1__create_users_table.sql

CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Migration 2: Ajouter une Colonne​

-- V2__add_email_to_users.sql

ALTER TABLE users
ADD COLUMN email VARCHAR(100) UNIQUE;

Migration 3: Créer une Autre Table avec FK​

-- V3__create_orders_table.sql

CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
total_amount DECIMAL(10, 2) NOT NULL,
status VARCHAR(20) DEFAULT 'PENDING',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_orders_user_id ON orders(user_id);

Migration 4: Insérer des Données​

-- V4__insert_initial_data.sql

INSERT INTO users (username, password, email) VALUES
('admin', '$2a$10$hashedpassword', 'admin@example.com'),
('user1', '$2a$10$hashedpassword', 'user1@example.com');

5. Comment Flyway Fonctionne​

La Table flyway_schema_history​

Flyway crée automatiquement une table pour tracker les migrations:

SELECT * FROM flyway_schema_history;
installed_rankversiondescriptiontypescriptchecksuminstalled_onexecution_timesuccess
11create users tableSQLV1__create_users_table.sql-1234562025-01-15 10:0045true
22add email to usersSQLV2__add_email_to_users.sql7890122025-01-15 10:0112true
33create orders tableSQLV3__create_orders_table.sql3456782025-01-16 09:0067true

Flux d'Exécution​


6. Configuration Spring Boot​

Configuration de Base​

# application.properties

# Activer Flyway
spring.flyway.enabled=true

# Emplacement des scripts (par défaut: classpath:db/migration)
spring.flyway.locations=classpath:db/migration

# Baseline (pour les BDD existantes)
spring.flyway.baseline-on-migrate=false
spring.flyway.baseline-version=1

Configuration Avancée​

# Schéma cible
spring.flyway.schemas=public

# Nettoyage (DANGEREUX en prod!)
spring.flyway.clean-disabled=true

# Validation
spring.flyway.validate-on-migrate=true

# Placeholder substitution
spring.flyway.placeholder-replacement=true
spring.flyway.placeholders.table_prefix=app_

Configuration YAML​

spring:
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: false
clean-disabled: true
validate-on-migrate: true

7. Migrations Répétables​

Cas d'Utilisation​

Certains objets doivent être recréés à chaque changement:

  • Vues (CREATE OR REPLACE VIEW)
  • Procédures stockées
  • Fonctions
  • Données de référence

Convention​

R__{description}.sql
│
└── Préfixe "R" (Repeatable)

Exemple​

-- R__create_active_users_view.sql

CREATE OR REPLACE VIEW active_users AS
SELECT id, username, email
FROM users
WHERE last_login > NOW() - INTERVAL '30 days';

Comportement:

  • Flyway calcule un checksum du fichier
  • Si le fichier change → réexécuté
  • Exécuté APRÈS toutes les migrations versionnées

8. Gestion des Environnements​

Structure Multi-Environnement​

src/main/resources/
├── db/
│ └── migration/
│ ├── V1__create_tables.sql # Tous les environnements
│ ├── V2__add_columns.sql
│ └── V3__create_indexes.sql
│
├── db-dev/
│ └── migration/
│ └── V1000__dev_test_data.sql # Données de test (dev seulement)
│
└── db-prod/
└── migration/
└── V1001__prod_config.sql # Config production

Configuration par Profil​

# application-dev.properties
spring.flyway.locations=classpath:db/migration,classpath:db-dev/migration

# application-prod.properties
spring.flyway.locations=classpath:db/migration,classpath:db-prod/migration

9. Intégration avec JPA/Hibernate​

Ordre d'Exécution​

# IMPORTANT: Flyway s'exécute AVANT Hibernate
spring.jpa.hibernate.ddl-auto=validate # Ne pas générer de schéma

# Ou pour le dev:
spring.jpa.hibernate.ddl-auto=none # Flyway gère tout

Workflow Recommandé​

astuce

En développement: Utilisez ddl-auto=validate pour vérifier que vos entités correspondent au schéma.

En production: Utilisez ddl-auto=none et laissez Flyway gérer tout.


10. Commandes Flyway​

Via Maven Plugin​

<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<configuration>
<url>jdbc:postgresql://localhost:5432/mydb</url>
<user>postgres</user>
<password>secret</password>
</configuration>
</plugin>
# Voir les migrations appliquées
mvn flyway:info

# Appliquer les migrations
mvn flyway:migrate

# Valider les migrations
mvn flyway:validate

# Réparer l'historique (attention!)
mvn flyway:repair

# Nettoyer la BDD (DANGEREUX!)
mvn flyway:clean

Exemple de Sortie flyway:info​

+-----------+---------+----------------------+------+---------------------+---------+
| Category | Version | Description | Type | Installed On | State |
+-----------+---------+----------------------+------+---------------------+---------+
| Versioned | 1 | create users table | SQL | 2025-01-15 10:00:00 | Success |
| Versioned | 2 | add email to users | SQL | 2025-01-15 10:01:00 | Success |
| Versioned | 3 | create orders table | SQL | 2025-01-16 09:00:00 | Success |
| Versioned | 4 | add indexes | SQL | | Pending |
+-----------+---------+----------------------+------+---------------------+---------+

11. Problèmes Courants et Solutions​

❌ Checksum Mismatch​

FlywayException: Validate failed: Migration checksum mismatch for migration version 2
-> Applied to database : -123456
-> Resolved locally : 789012

Cause: Le fichier de migration a été modifié après son exécution.

Solutions:

  1. Ne jamais modifier une migration déjà exécutée!
  2. Si c'est en dev: mvn flyway:repair
  3. Créer une nouvelle migration pour corriger

❌ Migration Not Found​

FlywayException: Detected resolved migration not applied to database: 3

Cause: Une migration existe en BDD mais pas dans les fichiers.

Solution: Restaurer le fichier de migration manquant.

❌ Out of Order Migration​

FlywayException: Detected resolved migration not applied to database: 2
(Applied migrations are: 1, 3)

Cause: Migration V2 ajoutée après V3.

Solution:

spring.flyway.out-of-order=true  # Autoriser les migrations hors ordre

❌ Failed Migration​

FlywayException: Migration V4__add_index.sql failed

Solution:

  1. Corriger le SQL dans le fichier
  2. Exécuter mvn flyway:repair (marque comme résolu)
  3. Exécuter mvn flyway:migrate

12. Best Practices​

✅ Règles d'Or​

1. NE JAMAIS modifier une migration déjà exécutée
→ Créer une nouvelle migration pour corriger

2. NE JAMAIS supprimer une migration exécutée
→ L'historique doit rester cohérent

3. TOUJOURS tester les migrations sur un environnement de test
→ Avant de déployer en production

4. TOUJOURS avoir un backup avant migration en production
→ Au cas où

5. Garder les migrations petites et focalisées
→ Une migration = une modification logique

✅ Nommage Clair​

-- ✅ BON
V1__create_users_table.sql
V2__add_email_column_to_users.sql
V3__create_orders_with_foreign_keys.sql

-- ❌ MAUVAIS
V1__changes.sql
V2__update.sql
V3__fix.sql

✅ Scripts Idempotents​

-- ✅ BON: Vérifie avant de créer
CREATE TABLE IF NOT EXISTS users (...);

-- ✅ BON: Vérifie avant d'ajouter une colonne (PostgreSQL)
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'users' AND column_name = 'phone') THEN
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
END IF;
END $$;

13. Résumé​

Points Clés​

ConceptDescription
FlywayOutil de migration de schéma versionné
V{n}__Préfixe pour migrations versionnées
R__Préfixe pour migrations répétables
flyway_schema_historyTable qui track les migrations
checksumHash du fichier pour détecter les modifications

Workflow Typique​

1. Créer un fichier V{n}__description.sql
2. Écrire le SQL
3. Démarrer l'application (ou mvn flyway:migrate)
4. Flyway exécute automatiquement
5. Vérifier avec mvn flyway:info

Configuration Minimale​

# Spring Boot + Flyway
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
spring.jpa.hibernate.ddl-auto=validate

🎯 Prochaine Étape​

Flyway est l'outil le plus populaire, mais Liquibase offre une alternative avec des fonctionnalités différentes. Voyons quand choisir l'un ou l'autre.

➡️ Chapitre 4: Migration avec Liquibase


⬅️ Retour au Module 7