Liquibase est un gestionnaire de mise à jour de base de donnée Il permet la mise à jour du schéma et des données. Le principe consiste à créer pour chaque évolution un “changelog” (c'est un fichier xml) et de le référencer dans le fichier de gestion des révisions, en général nommé master.xml.
Ce changelog ne sera joué qu'une seule fois (si il réussit)
Il faut tout de suite rentrer un peu plus dans les détails :
master.xml contient des fichier changelogs
changelog, qui contient des changeset
changeset id=XXXXX, qui contient
changeset entries qui sont fait les actions de modifications de la base
Pour fonctionner, liquibase va créer 2 tables supplémentaire dans la base de données :
<sxh java>
La description est parlante, à part le md5sum ; il est créé pour chaque changelog, lors de son exécution Il s'agit d'une empreinte générée à partir des éléments du fichier xml changelog touchant à la base de donnée (i.e le contenu des changeset entry) ; les autres éléments sont ignorés du calcul. Cela permet de l'authentifier.
Pendant son exécution, liquibase recalcule l'empreinte md5 tous les changelogs déjà exécutés et s'assure qu'il correspondent bien à celui historisé en base dans la table datachangelog. Cela démontre qu'aucun changesetlog n'a été modifié. Si il en trouve un, alors il plantera en fournissant la stacktrace ci-dessous.
</sxh>
<sxh java>
1 change sets check sum
classpath:config/liquibase/changelog/00000000000000_initial_schema.xml::00000000000001::jhipster is now: 7:c544e5ee3ae4aae8b6a8d0b554712f3a
liquibase.exception.ValidationFailedException: Validation Failed:
1 change sets check sum
classpath:config/liquibase/changelog/00000000000000_initial_schema.xml::00000000000001::jhipster is now: 7:c544e5ee3ae4aae8b6a8d0b554712f3a
at liquibase.changelog.DatabaseChangeLog.validate(DatabaseChangeLog.java:215)
at liquibase.Liquibase.update(Liquibase.java:208)
at liquibase.Liquibase.update(Liquibase.java:192)
at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:434)
...
</sxh>
Si aucun changelog exécuté n'a été modifié, et qu'un nouveau changelog doit être exécuté, alors liquibase tentera d'exécuter le nouveau changelog.
Il ne l'inscrira en base que si l'exécution complète n'a pas posée de problèmes.
<sxh xml>
<?xml version=“1.0” encoding=“utf-8”?> <databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<include file="classpath:config/liquibase/changelog/00000000000000_initial_schema.xml" relativeToChangelogFile="false"/> <include file="classpath:config/liquibase/changelog/20161201124308_added_entity_Category.xml" relativeToChangelogFile="false"/> <include file="classpath:config/liquibase/changelog/20161201124309_added_entity_CategorySet.xml" relativeToChangelogFile="false"/>
/> </sxh>
A noter que relativeToChangelogFile ne sert qu'à préciser si le chemin indiqué pour ce changelog est relatif au dossier de master.xml
<sxh xml>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>com.mattbertolini</groupId>
<artifactId>liquibase-slf4j</artifactId>
<version>2.0.0</version>
<scope>compile</scope>
</dependency> </sxh>
<sxh xml>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.2</version>
<dependencies>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.2-GA</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate4</artifactId>
<version>3.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.4.1.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
<configuration>
<changeLogFile>src/main/resources/config/liquibase/master.xml</changeLogFile>
<diffChangeLogFile>src/main/resources/config/liquibase/changelog/20180105220221_changelog.xml</diffChangeLogFile>
<driver>com.mysql.jdbc.Driver</driver>
<url>jdbc:mysql://localhost:3306/testify_jhi</url>
<defaultSchemaName>testify_jhi</defaultSchemaName>
<username>root</username>
<password>root</password>
<referenceUrl>hibernate:spring:fr.softeam.testify.domain?dialect=org.hibernate.dialect.MySQL5InnoDBDialect&hibernate.ejb.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy</referenceUrl>
<verbose>true</verbose>
<logging>debug</logging>
</configuration>
</plugin> </sxh>
Il est aussi possible de lancer liquibase au lancement de l'application web.
Cela se fait en utilisant la classe SpringLiquibase par exemple. Pour plus d'info, voir l'article projet testify
E1 : Trouver le plugin liquibase dans le pom.xml du projet testify_jhi :
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.2</version>
Ajouter au plugin liquibase les exécutions suivantes : <sxh xml>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>update</goal>
</goals>
<configuration>
<changeLogFile>src/main/resources/config/liquibase/master.xml</changeLogFile>
<diffChangeLogFile>src/main/resources/config/liquibase/changelog/20180117163143_changelog.xml</diffChangeLogFile>
<driver>com.mysql.jdbc.Driver</driver>
<url>jdbc:mysql://localhost:3306/testify_jhi</url>
<defaultSchemaName>testify_jhi</defaultSchemaName>
<username>root</username>
<password>root</password>
<referenceUrl>hibernate:spring:fr.softeam.testify.domain?dialect=org.hibernate.dialect.MySQL5InnoDBDialect&hibernate.ejb.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy</referenceUrl>
<verbose>true</verbose>
<logging>debug</logging>
</configuration>
</execution>
</executions>
</sxh>
E2 : Sous eclipse, indiquer Workspace : ${workspace_loc:/testify_jhi}
Goals : org.liquibase:liquibase-maven-plugin:update
Prerequis :
Voici mon fichier <sxh java>
driver: com.mysql.jdbc.Driver classpath: C:/Users/xavier/.m2/repository/mysql/mysql-connector-java/5.1.39/mysql-connector-java-5.1.39.jar;D:/Programmation/java/Projet/testify_jhi/src/main/resources url: jdbc:mysql://localhost:3306/testify_jhi username: root password: root
</sxh>
Exécuter :
java -jar <mavenFilePathTo>/liquibase-core-3.4.2.jar --changeLogFile="./config/liquibase/master.xml" validate
Il est aussi possible de ne pas se servir du fichier liquibase.properties et de passer tous les paramètres :
java -jar <mavenFilePathTo>/liquibase-core-3.4.2.jar \
--driver=com.mysql.jdbc.Driver \
--url=jdbc:mysql://localhost:3306/testify_jhi \
--username=root \
--password=root \
--classpath: <PathTo>/mysql-connector-java-5.1.39.jar;D:/Programmation/java/Projet/testify_jhi/src/main/resources \
--changeLogFile="./config/liquibase/master.xml" \
update
E1 : Faire ses modif dans le changetset d'id <idChangeset> le fichier xml changelog, et enregistrer le fichier
E2 : Relancer liquibase (validate ou update) Normalement, il devrait planter en indiquant que le fichier xml a été modifié et en fournissant le nouveau MD5 <newMD5> du changeset <idChangeset> Dans ce cas là, liquibase s'arrête et ne fera aucune update.
E3 :
update databasechangelog set md5sum=<newMD5> where id=<idChangeset>; commit;
E4 : Relancer liquibase ; cette fois-ci tout devrait être bon
java -jar <mavenFilePathTo>/liquibase-core-3.4.2.jar --changeLogFile="./config/liquibase/master.xml" clearCheckSums
Normalement, à la prochaine exécution de liquibase, tous les md5 sont regénérés.
Attention : clearCheckSums vide les MD5 de *TOUS* les changelogs
Il est possible de tagguer un état de la base. Cela permet de faire des retour arrière (“rollback”) pour remettre la base de donnée dans l'état où elle était à un tag donné.
Il suffit d'ajouter une ligne dans le fichier master.xml :
<include file="<newChangelogXmlFilePath>" relativeToChangelogFile="false"/>
De créer le fichier xml <newChangelogXmlFilePath> qui contient les instructions de modifications en base à exécuter. Ces instructions sont donc des tags xml, le site de liquibase fournit la syntaxe.
Suite à cela, en relancant liquibase par l'application ou en standalone, liquibase va identifier ce nouveau changelog, l'inscrire dans la table databasechangelog et tenter de l'exécuter.
Remarque importante : Le changelog ne sera inséré en base que si liquibase a réussi à complètement le jouer. =⇒ Il commit donc les changements en base par exécution de changelog entier.
=⇒ Cela permet de travailler à le faire passer en toute sécurité.