Présentation
Liquibase est un système de contrôle de version de base de données, cela concerne principalement la structure et, dans une moindre mesure, le contenu de la base de données. Dans le même temps, la description de la base de données d'une part est assez abstraite et permet l'utilisation de divers SGBD au niveau inférieur, et d'autre part, vous pouvez toujours passer au dialecte SQL d'un SGBD spécifique, ce qui est assez flexible. Liquibase est un projet open source établi et est activement utilisé en dehors de son environnement Java natif et ne nécessite pas de connaissance approfondie de Java pour fonctionner. Un format XML a été historiquement utilisé pour décrire la structure de base et les changements de base, mais maintenant YAML et JSON sont pris en charge en parallèle.
Dans cet article, nous résumerons brièvement l'expérience des générations précédentes et nous concentrerons sur la collaboration avec Liquibase à l'aide de Maven. Nous utiliserons Ubuntu comme système d'exploitation de test.
Autres articles sur Liquibase
Réglage de l'environnement
Il existe plusieurs façons de démarrer Liquibase, cependant, il est plus pratique d'utiliser Maven ou Gradle.
sudo apt install maven mvn -version
Ici, pom.xml agit comme un Makefile - il contient déjà toutes les dépendances, paramètres et profils nécessaires.
pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.test.db</groupId> <artifactId>db</artifactId> <version>1.0.0</version> <name>db</name> <description>Test Database</description> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <slf4j.version>1.7.24</slf4j.version> <logback.version>1.2.3</logback.version> <liquibase.version>3.6.2</liquibase.version> <postgresql.version>42.2.5</postgresql.version> <snakeyaml.version>1.23</snakeyaml.version> </properties> <dependencies> <!--Logging--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <!--JDBC drivers--> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>${postgresql.version}</version> </dependency> <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>${liquibase.version}</version> </dependency> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> <version>${snakeyaml.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.liquibase</groupId> <artifactId>liquibase-maven-plugin</artifactId> <version>${liquibase.version}</version> <configuration> <propertyFile>${profile.propertyFile}</propertyFile> <changeLogFile>${profile.changeLogFile}</changeLogFile> <dataDir>${profile.dataDir}</dataDir> <!-- log --> <verbose>${profile.verbose}</verbose> <logging>${profile.logging}</logging> <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase> </configuration> </plugin> </plugins> </build> <profiles> <!-- Development settings, -Denv=dev --> <profile> <id>dev</id> <activation> <property> <name>env</name> <value>dev</value> </property> </activation> <properties> <profile.propertyFile>dev/liquibase.properties</profile.propertyFile> <profile.changeLogFile>dev/master.xml</profile.changeLogFile> <profile.dataDir>dev/data</profile.dataDir> <profile.verbose>true</profile.verbose> <profile.logging>debug</profile.logging> </properties> </profile> <!-- Production settings, -Denv=prod --> <profile> <id>prod</id> <activation> <property> <name>env</name> <value>prod</value> </property> </activation> <properties> <profile.propertyFile>prod/liquibase.properties</profile.propertyFile> <profile.changeLogFile>prod/master.xml</profile.changeLogFile> <profile.dataDir>prod/data</profile.dataDir> <profile.verbose>false</profile.verbose> <profile.logging>info</profile.logging> </properties> </profile> </profiles> </project>
Nous lançons la mise à jour
Après avoir fait pom.xml, nous pouvons commencer à mettre à jour la base de données - la commande liquibase: update.
Pour cela, nous avons besoin de:
- Fichier liquibase.properties avec les paramètres de connexion à la base de données (nom d'utilisateur / mot de passe et éventuellement d'autres paramètres)
- fichier xml avec modifications de base
- script de démarrage de mise à jour de la base de données sh
Fichier de paramètres de connexion à la base de données
liquibase.properties
username=test password=test referenceUsername=test # #url=jdbc:postgresql://dev/test #referenceUrl=jdbc:postgresql://dev/test_reference
Fichier de modifications de base
Le concept principal de la base de données est ce que l'on appelle les changements de base (changesets). Ils peuvent inclure à la fois des changements structurels et des changements de données. Liquibase utilise les tables databasechangelog et databasechangeloglock pour surveiller les modifications appliquées.
<?xml version="1.1" encoding="UTF-8" standalone="no"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> <changeSet context="legacy" author="author (generated)" id="1"> <createTable tableName="test"> <column autoIncrement="true" name="id" type="SERIAL"> <constraints nullable="false"/> </column> <column name="user_name" type="VARCHAR(255)"/> <column name="preferences" type="TEXT"/> </createTable> </changeSet> </databaseChangeLog>
Script de démarrage de la mise à jour de la base de données
Ici liquibase: la mise à jour est exécutée pour le profil dev et la base de liquibase.url, qui est spécifié au format JDBC standard. Après la mise à jour, la table indiquée dans changeSet et deux tables de services databasechangelog et databasechangeloglock apparaissent dans la base de données .
#!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"
Génération SQL sans mise à jour de la base de données
Parfois, avant de commencer les modifications, vous devez regarder le contenu des requêtes générées. Les commandes liquibase: updateSQL et liquibase: rollbackSQL sont prévues à cet effet.
#!/usr/bin/env bash mvn liquibase:updateSQL\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified" > /tmp/script.sql
En savoir plus sur changeSet
Les modifications peuvent être dans différents formats, y compris SQL standard ou dans un fichier séparé.
Chaque modification peut inclure une section de restauration vous permettant d' annuler les modifications avec la commande liquibase: rollback . De plus, vous pouvez utiliser tagDatabase pour marquer les modifications, par exemple, pour y revenir plus facilement.
<changeSet context="legacy" author="author (generated)" id="1"> <createTable tableName="test"> <column autoIncrement="true" name="id" type="SERIAL"> <constraints primaryKey="true" primaryKeyName="test_pkey"/> </column> <column name="c1" type="VARCHAR(255)"/> <column name="c2" type="INTEGER"/> <column name="c3" type="SMALLINT"/> <column name="c4" type="VARCHAR(255)"/> <column name="c5" type="TEXT"/> <column name="c6" type="VARCHAR(255)"/> </createTable> </changeSet>
Embedded SQL
<changeSet context="legacy" author="author" id="1-domain-some-domain"> <sql> CREATE DOMAIN public.some_domain AS bigint; ALTER DOMAIN public.some_domain OWNER TO test; </sql> <rollback> DROP DOMAIN public.some_domain; </rollback> </changeSet>
Fichier SQL
<changeSet context="legacy" author="author" id="1-user"> <sqlFile dbms="postgresql" path="sql/some.sql" relativeToChangelogFile="true" /> <rollback> delete from "some"; </rollback> </changeSet>
Balises
<changeSet context="legacy" author="author" id="1-initial-changeset"> <tagDatabase tag="initial"/> </changeSet>
Contextes de lancement
Pour une gestion plus pratique de diverses configurations, par exemple, développement / production, des contextes peuvent être utilisés. Le contexte est spécifié dans l'attribut changeSet du contexte, puis lancé par Maven avec le paramètre -Dcontexts.
Changer avec le contexte
<changeSet context="legacy" author="author" id="1-initial-changeset"> <tagDatabase tag="initial"/> </changeSet>
Déclenchement des changements de contexte
#!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"\ -Dliquibase.contexts=non-legacy
Annuler les modifications
L'opération est l'opposé de la mise à jour, dans la plupart des cas, elle est prise en charge automatiquement. Pour d'autres, la tâche est possible via la section de restauration. Il est lancé par la commande liquibase: rollback.
Changer avec restauration
<changeSet context="legacy" author="author" id="1-domain-some-domain"> <sql> CREATE DOMAIN public.some_domain AS bigint; ALTER DOMAIN public.some_domain OWNER TO test; </sql> <rollback> DROP DOMAIN public.some_domain; </rollback> </changeSet>
Lancer la restauration
#!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"\ -Dliquibase.contexts=non-legacy
Comparaison
En cours de développement, il est pratique d'utiliser pour comparer deux bases de données existantes pour les modifications apportées. Dans les paramètres (ou paramètres de lancement), vous devrez ajouter un lien vers la base de données de référence et les données pour y accéder.
liquibase.properties
referenceUsername=test referenceUrl=jdbc:postgresql://dev/test_reference
Comparaison de circuits
Comparaison des schémas url et referenceUrl.
#!/usr/bin/env bash mvn liquibase:diff\ -Denv=dev\ -Dliquibase.referenceUrl="jdbc:postgresql://dev/test?prepareThreshold=0"\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.diffChangeLogFile=dev/diff.xml
Enregistrement du schéma
Il peut également être utile d'enregistrer le schéma de base de données actuel, avec ou sans données. Il faut garder à l'esprit que Liquibase enregistre un schéma qui ne correspond pas entièrement à l'original, par exemple, les domaines utilisés ou l'héritage devront être ajoutés séparément (voir Restrictions).
Sauvegarder un schéma sans prendre en compte les données
Enregistrement du schéma d'une base de données existante
#!/usr/bin/env bash mvn liquibase:generateChangeLog\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.outputChangeLogFile=dev/changelog.xml
Enregistrement d'un schéma avec des données
Enregistrement du schéma d'une base de données existante avec des données.
#!/usr/bin/env bash mvn liquibase:generateChangeLog\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.outputChangeLogFile=dev/changelog.xml
Limitations et problèmes
Travailler avec des données binaires dans la base de données
Il y a certains problèmes avec le téléchargement, la comparaison et l'utilisation de données binaires, en particulier un problème avec la génération de changements.
Héritage et colonnes communes
Code source
Solutions alternatives
Flyway
Avec Liquibase est populaire dans la communauté Java - http://flywaydb.org/documentation
Sqqitch
Équivalent Perl - http://sqitch.org
Fluentmigrator
Analogique pour .Net - https://github.com/schambers/fluentmigrator
Dbgeni
Analogue pour Ruby - http://dbgeni.appsintheopen.com/manual.html
Les applications
Structure du projet
pom.xml - maven makefile dev liquibase.properties - login/password etc master.xml - changesets
Comment ajouter une base de données à un projet existant
Fonctionnement des changements de base
En savoir plus sur la mise à jour
Plus sur la génération de changement
En savoir plus sur le SQL personnalisé
Traitement des types de données spécifiques à la base de données
<createTable tableName="t_name"> ... <column name="doubleArray" type="DOUBLE_ARRAY"/> ... </createTable> <modifySql dbms="postgresql"> <replace replace="DOUBLE_ARRAY" with="double precision[][]"/> </modifySql>
Autre