Liquibase est un outil très utile pour versionner sa base de données. La succession de refactoring à appliquer à une base peut-être décrite dans plusieurs formats de données (XML, YAML, JSON et SQL). Seulement il arrive qu’une migration soit “trop” complexe pour être décrite à partir des refactoring standards (ou alors tout simplement que l’on ne soit pas très à l’aise avec PL/SQL).
Dans ce cas on peut écrire un changement particulier en Java.
Implémenter un CustomChange
Liquibase propose deux interfaces pour créer son refactoring personnel, CustomTaskChange
et CustomSqlChange
.
La première permet d’appliquer des changements qui ne génèrent pas de SQL contrairement à la seconde.
Cette dernière est à privilégier quand c’est possible puisque cela permet de sauvegarder le SQL généré dans un fichier (via un dryRun
par exemple).
public class MyCustomChangeThatGenerateSql implements CustomSqlChange {
@Override
public SqlStatement[] generateStatements(final Database database) throws CustomChangeException {
List<SqlStatement> statements = new ArrayList<>();
JdbcConnection connection = (JdbcConnection) database.getConnection();
try {
ResultSet persons = connection.createStatement().executeQuery("select nom, prenom from person");
while (persons.next()) {
// Write your complex logic in here !
// and generate SqlStatement(s)
}
} catch (DatabaseException | SQLException e) {
throw new CustomChangeException(e);
}
SqlStatement insert = new InsertStatement(database.getDefaultCatalogName(), database.getDefaultSchemaName(), "person")
.addColumnValue("nom", "Gay")
.addColumnValue("prenom", "Jean-Christophe");
SqlStatement update = new UpdateStatement(database.getDefaultCatalogName(), database.getDefaultSchemaName(), "person")
.addNewColumnValue("prenom", "Jc")
.setWhereClause(String.format("nom='%s'", Gay))
statements.add(insert);
statements.add(update);
return statements.toArray(new SqlStatement[statements.size()]);
}
@Override
public String getConfirmationMessage() {
return null;
}
@Override
public void setUp() throws SetupException {}
@Override
public void setFileOpener(ResourceAccessor resourceAccessor) {}
@Override
public ValidationErrors validate(Database database) {
return null;
}
}
La principale logique se passe dans la méthode generateStatements
. L’API de Liquibase nous donne accès à la connexion Jdbc et il suffit de générer des SqlStatement
pour décrire son refactoring.
Le reste des méthodes à implémenter permet de valider la configuration, accéder à des fichiers, etc. La Javadoc explique tout ça.
Configurer son changeset
L’élément customChange
permet de déclarer la classe implémentant le refactoring.
<changeSet id="20140606-super-complex-change" author="jc.gay">
<customChange class="fr.jcgay.MyCustomChangeThatGenerateSql" />
</changeSet>
Et voilà on peut décrire des changements complexes dans son langage préféré !