Lorsque des modifications sont effectuer dans une application qui impacte le schema de base de données, celui doit subir des migrations. ToPIA fournit une API visant a assister le developpeur pour migrer un schema de base de données.
TODO approche migration par copy TOOD approche migration par requette sql
Pour commencer, topia doit connaitre l'ensemble des versions de la base de données, et la version actuelle de l'application. Si la version de l'application diffère de celle de la base de données, une migration sera effectuée. Après la migration, la version de la base de données est égale à celle de l'application.
La migration est effectuée par le service de migration de ToPIA. Il est necessaire de l'ajouter explicitement.
<dependency> <groupId>org.nuiton.topia</groupId> <artifactId>topia-service-migration</artifactId> <version>2.5.3</version> <scope>compile</scope> </dependency>
Pour commencer, il faut créer la classe definissant les versions.
public class DatabaseMigrationClass extends TopiaMigrationCallbackByClass {
protected static final Version VERSION_1 = new Version("1");
protected static final Version VERSION_2 = new Version("2");
protected static final Version VERSION_3 = new Version("3");
public DatabaseMigrationClass() {
super(new MigrationResolver());
}
protected static class MigrationResolver implements MigrationCallBackForVersionResolver {
@Override
public Class<? extends MigrationCallBackForVersion> getCallBack(Version version) {
Class<? extends MigrationCallBackForVersion> result = null;
if (version.equals(VERSION_1)) {
result = MigrationV0V1.class;
}
else if (version.equals(VERSION_2)) {
result = MigrationV1V2.class;
}
else if (version.equals(VERSION_3)) {
result = MigrationV2V3.class;
}
return result;
}
}
@Override
public Version[] getAvailableVersions() {
Version[] result = new Version[] { VERSION_1, VERSION_2, VERSION_3 };
return result;
}
@Override
public Version getApplicationVersion() {
Version appVersion = new Version(MyAppDAOHelper.getModelVersion());
return appVersion;
}
@Override
public boolean askUser(Version dbVersion, List<Version> versions) {
return true;
}
}
Ensuite, il faut créer une classe par migration.
Par exemple, voici la classe migrant le shema de la version 0 à la version 1 : MigrationV0V1.
public class MigrationV0V1 extends MigrationCallBackForVersion {
public MigrationV0V1(Version version, TopiaMigrationCallbackByClass callBack) {
super(version, callBack);
}
@Override
protected void prepareMigrationScript(TopiaContextImplementor tx,
List<String> queries, boolean showSql, boolean showProgression)
throws TopiaException {
queries.add("alter table SETOFVESSELS add column TECHNICALEFFICIENCYEQUATION VARCHAR(255);");
queries.add("alter table STRATEGY add column INACTIVITYEQUATIONUSED BIT default false;");
queries.add("alter table STRATEGY add column INACTIVITYEQUATION VARCHAR(255);");
queries.add("alter table STRATEGYMONTHINFO alter NUMBEROFTRIPS double;");
queries.add("alter table STRATEGYMONTHINFO alter MININACTIVITYDAYS double;");
}
}
Pour finir, il faut ajouter l'utilisation de la migration par ces classe dans le topia context. En effet, la migration est effectuée automatiquement lors de l'ouverture d'un TopiaContext.
Configuration:
config.put(TopiaMigrationService.TOPIA_SERVICE_NAME, TopiaMigrationEngine.class.getName()); config.put(TopiaMigrationService.MIGRATION_CALLBACK, DatabaseMigrationClass.getName());
ou dans un fichier de properties :
topia.service.migration=org.nuiton.topia.migration.TopiaMigrationEngine topia.service.migration.callback=org.test.myapp.DatabaseMigrationClass
Une autre idee est de ne pas utiliser hibernate mais kettle pour la migration des données. Nous aurions de la même façon dans le nom des tables un numero de version de schéma. Un fichier kettle decrirait la migration d'une version à une autre. Et les différents fichiers serait chaînés pour arriver au schéma souhaité.