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'interfaceMigration
- 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 packagedomaine.V1V2
- redéfinit la methode migrateFrom() pour indiquer que les donnees proviennent de
domaine.Personne
- implémente
migrate()
pour produire des tuples de typedomaine.Naissance
à partir de tuplesdomaine.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.