Migrations avec Flyway
Notions théoriques
Pourquoi gérer les migrations de base de données ?
Quand une application évolue, la structure de sa base de données change : nouvelles tables, nouvelles colonnes, modifications de contraintes. Sans outil de migration, chaque développeur doit appliquer manuellement les modifications SQL, ce qui entraîne des incohérences entre les environnements (dev, test, production).
Flyway résout ce problème en versionnant les scripts SQL exactement comme Git versionne le code source.
| Doctrine Migrations (Symfony) | Flyway (Spring Boot) |
|---|---|
php bin/console make:migration | Créer manuellement V2__description.sql |
php bin/console doctrine:migrations:migrate | Automatique au démarrage de l'application |
Table doctrine_migration_versions | Table flyway_schema_history |
Fichiers migrations/VersionXXXX.php | Fichiers db/migration/VN__description.sql |
Ajouter Flyway au projet
Dans pom.xml, ajoutez la dépendance :
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
Convention de nommage des scripts
Les fichiers de migration sont placés dans src/main/resources/db/migration/ et respectent la convention :
V{numéro}__{description}.sql
V: préfixe obligatoire (V majuscule){numéro}: numéro de version entier croissant (1,2,3...)__: deux underscores séparent le numéro de la description{description}: description en snake_case (mots séparés par_)
Exemples valides :
V1__init.sql
V2__add_resume_article.sql
V3__create_table_utilisateurs.sql
V4__add_index_email_utilisateur.sql
Une fois qu'un script Flyway a été exécuté en production, ne le modifiez jamais. Flyway stocke le checksum (empreinte) de chaque fichier dans flyway_schema_history. Si vous modifiez un fichier déjà exécuté, Flyway refusera de démarrer et lancera une erreur Validate failed. Pour modifier une table existante, créez un nouveau script V2__....
La table flyway_schema_history
À son premier démarrage, Flyway crée automatiquement une table flyway_schema_history qui enregistre chaque migration exécutée :
| installed_rank | version | description | script | checksum | success |
|---|---|---|---|---|---|
| 1 | 1 | init | V1__init.sql | -1234567 | true |
| 2 | 2 | add resume article | V2__add_resume_article.sql | 8765432 | true |
Au prochain démarrage, Flyway compare les fichiers SQL présents avec ceux déjà exécutés et n'exécute que les nouveaux.
Configuration avec spring.jpa.hibernate.ddl-auto
Avec Flyway, il faut désactiver la génération automatique de schéma par Hibernate et utiliser validate à la place :
# src/main/resources/application.properties ou application.yml
spring.jpa.hibernate.ddl-auto=validate
| Valeur | Comportement |
|---|---|
create | Supprime et recrée le schéma au démarrage (réservé aux premiers tests) |
create-drop | Crée au démarrage, supprime à l'arrêt |
update | Modifie le schéma existant (dangereux en prod) |
validate | Vérifie que le schéma SQL correspond aux entités Java (sans modifier) |
none | Ne fait rien |
create ou update peuvent supprimer des données ou modifier le schéma de façon imprévue. Avec Flyway, utilisez validate : Hibernate vérifie que votre base correspond à vos entités et lève une erreur au démarrage si ce n'est pas le cas.
Exemples de scripts de migration
V1__init.sql — Création initiale des tables :
CREATE TABLE articles (
id BIGINT NOT NULL AUTO_INCREMENT,
titre VARCHAR(255) NOT NULL,
contenu TEXT NOT NULL,
date_creation DATETIME,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE utilisateurs (
id BIGINT NOT NULL AUTO_INCREMENT,
email VARCHAR(180) NOT NULL,
password VARCHAR(255) NOT NULL,
role VARCHAR(50),
PRIMARY KEY (id),
UNIQUE KEY uk_utilisateurs_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
V2__add_resume_article.sql — Ajouter une colonne :
ALTER TABLE articles
ADD COLUMN resume VARCHAR(500) AFTER titre;
Vérifier l'état des migrations
# Afficher l'état des migrations (version, description, date d'exécution)
mvn flyway:info
Exemple pratique
Structure complète d'un projet MonBlog avec Flyway :
src/main/resources/
├── application.properties
└── db/
└── migration/
├── V1__init.sql
└── V2__add_resume_article.sql
application.properties :
spring.datasource.url=jdbc:mysql://localhost:3306/monblog
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=validate
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
Au démarrage, Spring Boot détecte Flyway, exécute les scripts non encore appliqués et valide le schéma avec Hibernate.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Dans ce TP, vous allez mettre en place Flyway dans le projet MonBlog et créer les scripts de migration initiaux.
Étape 1 — Ajouter Flyway à pom.xml
Ajoutez les deux dépendances Flyway dans le pom.xml.
flyway-core contient le moteur de migration. flyway-mysql ajoute le support spécifique à MySQL (dialecte SQL, gestion des types). Les deux sont nécessaires pour un projet Spring Boot + MySQL.
Étape 2 — Configurer application.properties
Même en développement, utilisez validate dès que Flyway est en place. Cela vous force à créer un script de migration pour chaque changement de schéma — ce qui documente l'évolution de votre base et prépare le terrain pour la production.
Étape 3 — Créer le script V1__init.sql
Créez le fichier src/main/resources/db/migration/V1__init.sql avec les tables articles et utilisateurs.
Utilisez CREATE TABLE IF NOT EXISTS pour rendre vos scripts plus robustes, même si Flyway ne les exécute normalement qu'une seule fois. Cela protège contre les exécutions manuelles accidentelles en dehors de Flyway.