ToPIA Migration Service

ToPIA Migration Service est un module ToPIA chargé d'effectuer la migration d'une base de données existante sans perte de données.

Configuration

Ce service doit disposer de quelques proprietés de configuration pour effectuer la migration d'une base de données.

Ces propriétés sont fournies au service via un TopiaContext et font donc partie de la configuration de l'application.

Configuration de la base de données

hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.connection.username=sa
hibernate.connection.password=
hibernate.connection.driver_class=org.h2.Driver

topia.persistence.directories=directory1,directory2
topia.persistence.classes=classImpl1,classImpl2

Ces informations servent à créer une configuration hibernate (qui contient les informations de connexion et les mappings de l'application).

Les lignes commencant par "hibernate" sont spécifiques à hibernate et au type de base de données utilisé. Les lignes suivantes sont spécifiques à ToPIA mais contiennent les mappings indispensable pour créer le schéma de la base de données après migration.

Configuration des anciens mappings

La configuration doit contenir ces propriétés :

topia.service.migration.mappingsdir=oldmappings
topia.service.migration.modelnames=model1,model2,model3

qui spécifie le répertoire de recherche des anciens mappings pour les différents modèles.

Ce dossier contient ensuite un sous-dossier par modèle comportant chacun un sous-dossier par version par version (nommé X, X étant la version), avec pour chaque dossier, l'ensemble des mappings hibernate de cette version.

Exemple :

oldmappings/
   model1/
       1/
           Class1.hbm.xml
           Class2.hbm.xml
           Class3.hbm.xml
       2/
           Class1.hbm.xml
           Class2New.hbm.xml
           Class3.hbm.xml
       2.2/
           Class2.hbm.xml
           Class3.hbm.xml
           Class4New.hbm.xml

Configuration de la version

La configuration doit contenir une propriété :

topia.service.migration.version=3.5.1 (exemple)

Cette propriété renseigne la version courante de l'application. Le modèle de classes doit contenir un tag "version" indiquant la version courante du modèle.

Lors de la migration ces deux versions seront comparées pour déterminer les mappings à utiliser.

Configuration du callback

Il est possible de définir une classe de type MigrationCallbackHandler, pour interagir, par exemple, avec l'utilisateur et lui demander s'il faut migrer la base de données.

Ces callback doivent implémenter MigrationCallbackHandler et se trouver dans la configuration:

topia.service.migration.callbackhandlers=org.nuiton.test.MyCallbackHandler

Configuration du service

Enfin pour utiliser le service, il faut l'activer. La configuration doit contenir la propriétés suivante :

topia.service.migration=org.nuiton.topia.migration.TopiaMigrationServiceImpl

Utilisation

Ce module étant un service ToPIA, il doit être activé pour pouvoir s'exécuter.

Il commence par se connecter au SGBD, vérifie si les versions diffèrent, et effectue la migration si besoin.

Dans le cas où la version ne peut pas être deterninée, il considère que le schema en base est en version V0 (les mppings de cette version doivent être fournit). Dans ce cas, il effectue en plus une détection des tables pour savoir si le schéma existe deja. S'il n'existe pas, il ne tente donc pas d'effetuer une migration.

Classes de migration

Pour savoir comment migrer les données, le développeur utilisant le module de migration doit produire des classes Java de migration (une par classe nécéssitant une modification et par version).

Ces classes doivent :

  • hériter de la classe AbstractMigration ou de l'interface Migration
  • se trouver dans un sous package des classes d'implémentation référencées par les mappings. Ce package doit se nommer VnVm où:
    • n est la version de départ de migration
    • m la version d'arrivée
  • respecter une convention de nommage de la forme MigrationClass où:
    • Class est le nom de l'entité devant être migrée

    Exemple, pour migrer une Personne d'une version 2 à 2.1 le nom de la classe sera : V2V2_1.MigratePersonne.java

    Note: les "." étant interdits dans le nom de fichier, ils sont remplacés par le caractère "_".

Ensuite, chaque classe doit :

  • implémenter au moins la méthode migrate(MapAdapter, MapHelper) cette méthode prend une MapAdapter en paramètre, pour modifier un tuple et un MapHelper pouvant servir à retrouver des informations sur le reste des tuples de la base
  • surcharger (si besoin) la méthode public ProxyClass migrateFrom() dans le cas où les tuples à modifier proviennent d'une classe différente de la classe courante.

Exemple :

Ici, la modification porte sur la transformation de l'attribut timestampNaissance de la classe domaine.Personne en une nouvelle table domaine.Naissance, effectée dans le changement de la version 1 à la version 2 :

// migrateFrom()
public ProxyClass migrateFrom() {
        return new SimpleProxyClass("domaine.Personne");
}

// migrate(MapAdapter, MapHelper)
public void migrate(MapAdapter map, MapHelper helper) {

        // map d'entree vide, conversion du timestamp
        // en jour, mois, annee
        try {
                Long timestamp = (Long) map.getOldValue("timestampNaissance");
                Calendar c = Calendar.getInstance();
                c.setTimeInMillis(timestamp);
                map.setValue("jour", c.get(Calendar.DAY_OF_MONTH));
                map.setValue("mois", c.get(Calendar.MONTH));
                map.setValue("annee", c.get(Calendar.YEAR));
        } catch (ExceptionAttributeUndefined e) {
                e.printStackTrace();
        }
}

Donc cette classe :

  • doit se nommer MigrateNaissance.java et se trouver dans le package domaine.V1V2
  • redéfinit la methode migrateFrom() pour indiquer que les donnees proviennent de domaine.Personne
  • implémente migrate() pour produire des tuples de type domaine.Naissance à partir de tuples domaine.Personne

Création de schéma

Dans le cas où l'application est ammenée à créer un schéma de base de données, elle doit en informer le module de migration pour que celui-ci renseigne la version du schéma créé.

Le module s'enregistre automatiquement aupres de ToPIA pour savoir quand celui-ci a créé un nouveau schéma. Il renseigne donc automatiquement la version par la suite.