4 minute read

Índice de temario

Día Tema a tratar
1 Definiendo objetivos
2 Proyecto inicial
3 Endpoint básico
4 Entidades y persistencia
5 Transaccionalidad
6 Migraciones
7 Manejo de excepciones

Día 6. Migraciones. ¿Usar Flyway o Liquibase?

Haciendo pruebas de cómo usar Kotlin con SpringBoot en su conjunto, buscaba una herramienta que me pudiera gestionar las migraciones.

Buscaba algo con las siguientes características:

Features
Compatibilidad con varias bases de datos
Histórico de migraciones
Poder hacer Rollback
Herramienta de Diff
Dry run
Agnóstico de la base de datos
Formatos
Integrado con Spring
Cliente de consola

Cuando busqué por primera vez en internet. Encontré muchas reseñas hacia Flyway. Como por efecto no me quedo con la primera opción sin buscar más seguí buscando… y encontré Liquibase.

Ahora tenía dos elementos para poder enfrentarlos en sus versiones gratuitas y ampliar los requisitos si alguna de ellas me daba algo que no sabía que necesitaba.

Features Flyway Liquibase
Compatibilidad con varias bases de datos
Histórico de migraciones
Poder hacer Rollback De pago
Herramienta de Diff Usar JPABuddy de IntelliJ
Dry run De pago
Agnóstico de la base de datos
Formatos SQL, Java SQL, XML, YAML, JSON
Integrado con Spring Sólo para migrar
Cliente de consola

Flyway VS Liquibase. Ventajas e inconvenientes de cada uno.

Si bien Flyway está más integrado con Spring, con lo que puedes hacer cosas con relativa facilidad en los tests, Liquibase es agnóstico de la base de datos. Eso quiere decir que en lugar de escribir SQL, usamos un XML para definir las características de nuestra base de datos, y dependiendo de la conexión de BBDD que tenga, el SQL que se genere será más específico.

Para muestra un botón… definir un UUID con Flyway requiere hacer una SQL específica para PostgreSQL, ya que PostgreSQL tiene un tipo específico para este tipo de dato. Al contrario que Liquibase, que nosotros le definimos una especificación y él genera la SQL a medida.


Configurar Flyway

La verdad es que configurarlo es bastante sencillo. Agregar sus dependencias en el fichero build.gradle.kts.

dependencies {
...
 	runtimeOnly("org.flywaydb:flyway-core:8.3.0")
...
}

Definir su configuración en application.properties

spring.flyway.enables=true
spring.flyway.locations=classpath:/db/scripts/migration
spring.flyway.schemas=public

Y agregarle scripts a la carpeta que hemos definido anteriormente, dentro de main/resources. Eso sí… siguiendo la nomenclatura de versiones que exige Flyway, que sigue la plantilla __.sql que se describe en su documentación .

En esta imagen os podéis hacer una idea. Recodad que los rollback son de pago. En la versión gratuita sólo podremos hacer la primera opción y la última.

flyway migration versions

En nuestro caso sería V1_0__create_user_schema.sql con el siguiente contenido:

CREATE TABLE public.users (
	id uuid NOT NULL,
	username varchar(250) NOT NULL,
	CONSTRAINT users_pkey PRIMARY KEY (id)
);

Con esto ya estamos listos. Al arrancar nuestra aplicación, cargarálos scripts y los aplicaráa nuestra conexión de base de datos.


Configurar Liquibase

Configurar Liquibase es similar a Flyway. Agregamos sus dependencias en el fichero build.gradle.kts.

dependencies {
...
	implementation("org.liquibase:liquibase-core")
...
}

Definimos su configuración en application.properties

spring.liquibase.change-log=classpath:db/db.changelog-master.xml
#spring.liquibase.dropFirst=true (opción si estamos en local y queremos limpiar la base de datos al arrancar)

Y ya podemos crear el fichero que hemos definido anteriormente, dentro de main/resources.

En este caso, la estrategia de Liquibase es diferente. Siguiendo su documentación de buenas prácticas , se sirve de un fichero y luego nosotros vamos creando nuestra estructura de migraciones haciendo “includes” de esta forma.

flyway migration versions

Y aquí podemos ver el contenido de un changelog.

flyway migration versions

En nuestro caso, haremos lo mismo. Creamos el xml inicial que definimos en application.properties.

<?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"
                   xmlns:pro="http://www.liquibase.org/xml/ns/pro"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd
                      http://www.liquibase.org/xml/ns/pro
                      http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.1.xsd">

    <includeAll path="./db/changelogs"/>
</databaseChangeLog>

y dentro creamos un fichero con este aspecto.

<?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"
                   xmlns:pro="http://www.liquibase.org/xml/ns/pro"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd
                      http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.1.xsd">
    
    <changeSet id="202112231812" author="Fernando Aparicio">
        <createTable tableName="users">
            <column name="id" type="uniqueidentifier">
                <constraints primaryKey="true" />
            </column>
            <column name="username" type="varchar(250)">
                <constraints nullable="false"/>
            </column>
        </createTable>
    </changeSet>
</databaseChangeLog>

Al arrancar la aplicación, ejecutará las migraciones.


Bonus track Liquibase

En Liquibase puedes ejecutar SQL si lo necesitas. Lo interesante de todo esto es que tienes que definirle para qué bases dedatos es compatible dicha query. Así puedes curarte en salud.

<changeSet  author="liquibase-docs"  id="sql-example">
  <sql dbms="!h2, oracle, mysql"
   endDelimiter="\nGO"
   splitStatements="true"
   stripComments="true">insert into person (name) values ('Bob')
   
    <comment>What about Bob?</comment>
   </sql>
</changeSet>

https://docs.liquibase.com/workflows/liquibase-community/creating-config-properties.html

Tabla comparativa Free vs De pago

https://flywaydb.org/download

https://www.liquibase.com/pricing


comments powered by Disqus