Liquibase y Maven

Introduccion


Liquibase es un sistema de control de versión de base de datos, esto se refiere principalmente a la estructura y, en menor medida, al contenido de la base de datos. Al mismo tiempo, la descripción de la base de datos, por un lado, es bastante abstracta y permite el uso de varios DBMS en el nivel inferior, y por otro lado, siempre puede cambiar al dialecto SQL de un DBMS específico, que es bastante flexible. Liquibase es un proyecto de código abierto establecido y se utiliza activamente fuera de su entorno nativo de Java y no requiere un conocimiento profundo de Java para funcionar. Históricamente, se ha utilizado un formato XML para describir la estructura base y los cambios base, pero ahora YAML y JSON son compatibles en paralelo.


En este artículo, resumiremos brevemente la experiencia de generaciones anteriores y nos centraremos en trabajar con Liquibase utilizando Maven. Usaremos Ubuntu como sistema operativo de prueba.


Otros artículos sobre Liquibase



Entorno


Hay varias formas de iniciar Liquibase, sin embargo, es más conveniente usar Maven o Gradle.


sudo apt install maven mvn -version 

Aquí pom.xml actúa como un Makefile: ya contiene todas las dependencias, configuraciones y perfiles necesarios.


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> 

Lanzamos actualización


Después de haber hecho pom.xml, podemos comenzar a actualizar la base de datos, el comando liquibase: update.


Para esto necesitamos:


  • Archivo liquibase.properties con configuraciones para conectarse a la base de datos (nombre de usuario / contraseña y posiblemente otros parámetros)
  • archivo xml con cambios base
  • script de inicio de actualización de base de datos sh

Archivo de configuración de conexión de base de datos


liquibase.properties


 username=test password=test referenceUsername=test #     #url=jdbc:postgresql://dev/test #referenceUrl=jdbc:postgresql://dev/test_reference 

Archivo de cambios base


El concepto principal de liquibase son los llamados cambios de base (conjuntos de cambios). Pueden incluir cambios estructurales y cambios de datos. Liquibase utiliza las tablas databasechangelog y databasechangeloglock para monitorear los cambios aplicados.


 <?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 inicio de actualización de base de datos


Aquí liquibase: la actualización se ejecuta para el perfil de desarrollo y la base de liquibase.url, que se especifica en el formato estándar JDBC. Después de la actualización, la tabla indicada en changeSet y dos tablas de servicio databasechangelog y databasechangeloglock aparecen en la base de datos .


 #!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified" 

Generación de SQL sin actualizar la base de datos.


A veces, antes de comenzar los cambios, debe mirar el contenido de las solicitudes generadas. Los comandos liquibase: updateSQL y liquibase: rollbackSQL están destinados para este propósito.


 #!/usr/bin/env bash mvn liquibase:updateSQL\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified" > /tmp/script.sql 

Más sobre el cambio


Los cambios pueden estar en diferentes formatos, incluyendo sql regular o en un archivo separado.


Cada cambio puede incluir una sección de reversión que le permite revertir los cambios con el comando liquibase: rollback . Además, puede usar tagDatabase para marcar cambios, por ejemplo, para retroceder allí de manera más conveniente.


Formato normal


 <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> 

SQL incorporado


 <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> 

Archivo SQL


 <changeSet context="legacy" author="author" id="1-user"> <sqlFile dbms="postgresql" path="sql/some.sql" relativeToChangelogFile="true" /> <rollback> delete from "some"; </rollback> </changeSet> 

Etiquetas


 <changeSet context="legacy" author="author" id="1-initial-changeset"> <tagDatabase tag="initial"/> </changeSet> 

Contextos de lanzamiento


Para una gestión más conveniente de varias configuraciones, por ejemplo, desarrollo / producción, se pueden usar contextos. El contexto se especifica en el atributo changeSet del contexto y luego Maven lo inicia con el parámetro -Dcontexts.


Cambiar con el contexto


 <changeSet context="legacy" author="author" id="1-initial-changeset"> <tagDatabase tag="initial"/> </changeSet> 

Disparo de cambios de contexto


 #!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"\ -Dliquibase.contexts=non-legacy 

Revertir cambios


La operación es lo opuesto a la actualización, en la mayoría de los casos es compatible automáticamente. Para otros, la tarea es posible a través de la sección de reversión. Es lanzado por el comando liquibase: rollback.


Cambiar con reversión


 <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> 

Lanzar reversión


 #!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"\ -Dliquibase.contexts=non-legacy 

Comparación


En desarrollo, es conveniente usar para comparar dos bases de datos existentes para los cambios realizados. En la configuración (o parámetros de inicio), deberá agregar un enlace a la base de datos de referencia y los datos para acceder a ella.


liquibase.properties


 referenceUsername=test referenceUrl=jdbc:postgresql://dev/test_reference 

Comparación de circuitos


Comparación de los esquemas url y 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 

Esquema de ahorro


También puede ser útil guardar el esquema de la base de datos actual, con o sin datos. Debe tenerse en cuenta que Liquibase guarda un esquema que no corresponde totalmente al original, por ejemplo, los dominios utilizados o la herencia deberán agregarse por separado (ver Restricciones).


Guardar un esquema sin tener en cuenta los datos


Guardar el esquema de una base de datos existente.


 #!/usr/bin/env bash mvn liquibase:generateChangeLog\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.outputChangeLogFile=dev/changelog.xml 

Guardar un esquema con datos


Guardar el esquema de una base de datos existente con datos.


 #!/usr/bin/env bash mvn liquibase:generateChangeLog\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.outputChangeLogFile=dev/changelog.xml 

Limitaciones y problemas


Trabajando con datos binarios en la base de datos


Existen ciertos problemas con la carga, comparación y uso de datos binarios, en particular, un problema con la generación de cambios.



Herencia y columnas comunes



Código fuente



Soluciones alternativas


Flyway


Junto con Liquibase es popular en la comunidad Java: http://flywaydb.org/documentation


Sqqitch


Perl equivalente - http://sqitch.org


Inmigrante fluido


Análogo para .Net - https://github.com/schambers/fluentmigrator


Dbgeni


Análogo para Ruby - http://dbgeni.appsintheopen.com/manual.html


Aplicaciones


Estructura del proyecto


 pom.xml - maven makefile dev liquibase.properties - login/password etc master.xml - changesets 

Cómo agregar liquibase a un proyecto existente



Cómo funcionan los cambios de base



Más información sobre el cambio de formato



Más acerca de la actualización



Más sobre la generación de cambios



Más información sobre SQL personalizado



Procesamiento de tipos de datos específicos de la base de datos


 <createTable tableName="t_name"> ... <column name="doubleArray" type="DOUBLE_ARRAY"/> ... </createTable> <modifySql dbms="postgresql"> <replace replace="DOUBLE_ARRAY" with="double precision[][]"/> </modifySql> 

Otros


Source: https://habr.com/ru/post/436994/


All Articles