Accueil > Java > Automatiser les changements de schéma de base de données avec Flyway

Automatiser les changements de schéma de base de données avec Flyway

J’ai été intrigué par le système de mise à jour de base de données de l’appliation Sonar. Quand vous installez une nouvelle version, l’application vous indique que votre base de données est en version x et qu’il faut la migrer en version y. Un clic et un peu de patience plus tard, la mise à jour de la base de données est effective.

J’ai également rencontré le même système de mise à jour pour le portail projet Redmine. Le point commun entre ces deux outils : ils sont basés sur Ruby On Rails, le fameux framework intégré de développement web basé sur le langage Ruby.

Ruby On Rail intègre un outil nommé Migrations qui permet en effet de spécifier des migrations unitaires de base de données, le framework permettant de les appliquer de manière incrémentale.

En Java, les outils de mapping objet/relationnel disposent de fonctions similaires. Par exemple Hibernate sait générer le modèle de base de donnée (DDL) qui correspond à vos entités JPA . Il sait également mettre à jour une base de données pour lui ajouter des éléments (propriété hibernate.hbm2ddl.auto). Dans de nombreux cas c’est suffisant. Cependant certains cas ne sont pas gérés, par exemple le changement de type d’une colonne ou la suppression de colonnes.

J’ai récemment rencontré un cas ou nous avions besoin d’aller plus loin, en effet les applications traversent de nombreux environnements de qualification avant d’arriver en production. Dans ce cas les opérations manuelles sont à éviter le plus possible. J’ai donc recherché un outil équivalent à Migrations mais en Java.

J’ai trouvé mon bonheur avec Flyway, une librairie OpenSource (License Apache 2.0) qui permet d’automatiser les changements de schéma. L’idée est simple :

  • Flyway stocke dans une table (SCHEMA_VERSION) un journal des scripts déja executés sur cette base de données
  • L’application embarque les scripts SQL suivant une convention de nommage
  • Au démarrage de l’application, Flyway calcule l’écart entre la table SCHEMA_VERSION et les scripts présents dans votre application et applique les nouveaux scripts
De plus il est possible d’écrire les scripts en SQL mais aussi de les écrire en Java pour les opérations plus complexes. Par exemple pour adapter les données au nouveau schéma.
Pour intégrer flyway dans votre application, il est nécessaire d’ajouter la librairie flyway-core qui s’appuie sur spring-jdbc.
Pour les utilisateurs de maven, ajouter cette dépendance dans votre pom :
<!-- Migrations de schémas SQL -->
<dependency>
  <groupId>com.googlecode.flyway</groupId>
  <artifactId>flyway-core</artifactId>
  <version>1.4</version>
</dependency>

Les fichiers SQL doivent se trouver dans le classpath de l’application à l’exécution, dans un package db.migration. Les utilisateurs de maven les placeront donc dans src/main/resources/db/migration . Les fichiers doivent être nommés sur le pattern suivant : VX_yyy_zzz.sql, X représentant le numéro de version et yyy_zzz étant un libellé de version. Par exemple : V1_initialize.sql ou V6_parameter_table.sql .

Pour lancer la migration, une API est disponible. Toutes les opérations sont disponibles dans la classe Flyway, voici un exemple d’utilisation :

Flyway flyway = new Flyway();
flyway.setDataSource(dataSource);
flyway.migrate();

L’intégration avec Spring est soignée, il suffit de déclarer le bean avec une méthode d’initialisation

<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate">
  <property name="dataSource" ref="dataSource"/>
</bean>
Pour écrire un script de migration en Java, la encore il faut suivre une convention de nommage. Les classes  doivent se trouver dans le package db.migration et suivre le même pattern de nommage que les scripts. Par exemple : V4_settings_migration.java. Les classes doivent également implémenter l’interface JavaMigration.
Par exemple :
package db.migration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

import com.googlecode.flyway.core.migration.java.JavaMigration;

public class V54_sample_migration implements JavaMigration {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Override
	public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
		logger.info("V54_sample_migration STARTING");
		int countOfActorsNamedJoe = jdbcTemplate.queryForInt("select count(0) from actors where first_name = ?", "Joe");
		jdbcTemplate.update("update stats set count = ? where first_name = ?", countOfActorsNamedJoe, "Joe");
		logger.info("V54_sample_migration ENDED");
	}
}

Toutes les conventions de nommage sont configurables (package de base, préfixe et suffixe des scripts, …) . Pour assurer les évolutions d’un modèle de données existant, il est nécessaire d’ajuster la propriété disableInitCheck à true dans le cas contraire Flyway déclenche une exception.

Bref un outil simple et extrêmement pratique pour rendre le déploiement de vos applications un peu plus fluide.

Étiquettes : ,
  1. 5 juillet 2011 à 16:32

    Dans le même genre, s’appuyant sur les dialect hibernate:
    https://github.com/spreadthesource/tapestry5-db-migrations

  1. No trackbacks yet.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :