Cómo utilizar Flyway para la migración de bases de datos en Spring Boot

        En este artículo, veremos cómo usar Flyway para administrar esquemas de bases de datos SQL en aplicaciones Spring Boot.

        En este artículo, veremos cómo usar Flyway para administrar esquemas de bases de datos SQL en aplicaciones Spring Boot.
Flyway es una herramienta de migración de bases de datos que proporciona historial de migración y funcionalidad de reversión, y nos permite separar la capa relacionada con el esquema de la base de datos de la aplicación de la capa de entidad de la base de datos.

Configuraciones de la aplicación

La aplicación Spring Boot que usaremos se puede generar usando este enlace Spring Initializr. Contiene todas las dependencias necesarias.
Después de descargar la aplicación y resolver las dependencias, crearemos una nueva base de datos de Postgres llamada spring-boot-flyway y configuraremos la aplicación para conectarnos a ella.

Listado 2.1  propiedades.de.aplicación :

spring.datasource.url=jdbc:postgresql://localhost:5432/spring-boot-flyway
spring.datasource.username=demo
spring.datasource.password=demo

De forma predeterminada, Flyway busca en el directorio db/migration/ en el classpath archivos de migración que contengan declaraciones SQL para administrar tablas y registros de bases de datos. 

Para versiones anteriores de la biblioteca, es posible que necesitemos crear un archivo de texto vacío llamado .keep en resources/db/migration/  para asegurarnos de que este directorio esté compilado y disponible durante el inicio de la aplicación para evitar errores.

Una vez hecho esto, ahora podemos iniciar la aplicación y debería ejecutarse correctamente.

uso básico

La forma en que funciona Flyway es que creamos un archivo de migración en el directorio resources/db/migration y Spring Boot ejecuta automáticamente el script de migración desde que agregamos la dependencia de Flyway al classpath en la Sección 2 .

Listado 3.1  V1__Users.sql :

CREATE TABLE IF NOT EXISTS users
(
    id    SERIAL,
    email VARCHAR(200) NOT NULL,
    name  VARCHAR(200) NOT NULL,
    PRIMARY KEY (id)
);

Tomémonos un momento para examinar el fragmento de código del Listado 3.1. El nombre de archivo V1__Users.sql sigue ciertas convenciones:

  • V  " indica que se trata de una migración versionada.
  • El " 1  " después  de la V es el número de versión real. También puede ser "  V1_1  ", que se traducirá a la versión 1.1.
  • Le sigue el separador "  __  " (dos guiones bajos). Esto separa la información de la versión del nombre del archivo de migración (Usuarios en este caso ).
  • La última parte "  .sql  " es la extensión; por lo tanto, el archivo contiene una declaración SQL simple.

En este punto, reiniciar la aplicación creará la tabla de usuarios en la base de datos. Además, podemos ver que hay otra tabla que no creamos explícitamente:  Flyway_schema_history  .

Flyway_schema_history lo utiliza el propio Flyway para realizar un seguimiento de las migraciones aplicadas . Si falta esta tabla, Flyway asumirá que estamos inicializando la base de datos por primera vez y ejecutará todas las migraciones en el orden del número de versión.

Cuando existe la tabla Flyway_schema_history , Flyway solo aplicará archivos de migración más nuevos que no se hayan aplicado antes. Esto significa que, para agregar una nueva tabla, solo necesitamos crear un archivo de migración actualizado con un número de versión actualizado y reiniciar la aplicación.

En lugar de utilizar SQL, también podemos escribir scripts de migración en Java . En el estilo de migración de Java, nuestros archivos de migración son clases de Java que deben extender BaseJavaMigrationclases abstractas e implementar migratemétodos.

Los IDE generalmente no esperan que las clases Java estén en el directorio de recursos, por lo que crearemos un nuevo paquete llamado db/migration en src/main/java . Es muy importante saber que este nuevo paquete db/migration debe estar ubicado en el directorio src/main/jav .

Creemos una nueva migración de Java para agregar la nueva tabla:

Listado 3.2  V2__Posts.java  :

public class V2__Posts extends BaseJavaMigration {
    @Override
    public void migrate(Context context) throws Exception {
        var sql = """
                CREATE TABLE posts (
                     id SERIAL,
                     author_id INT NOT NULL,
                     post TEXT NOT NULL,
                     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                     updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                     PRIMARY KEY (id)
                );
                """;
        try(var statement = context.getConnection().createStatement()) {
            statement.execute(sql);
        }
    }
}

La ventaja de utilizar migraciones de Java sobre archivos SQL es que podemos agregar lógica, condiciones y validaciones personalizadas que no son posibles con SQL simple. Por ejemplo, podemos comprobar si existe otra tabla u obtener algún valor del entorno, etc.

Como ya habrás adivinado, sí, es posible mezclar migraciones de estilo SQL y Java en la misma base de código, siempre y cuando nos aseguremos de que la ubicación de Flyway sea la misma en ambos casos.

Configuración y personalización de rutas migratorias

Hasta ahora hemos estado usando el comportamiento predeterminado de Flyway. Podemos ajustar aún más Flyway para adaptarlo a nuestras necesidades. Por ejemplo, podemos cambiar la ubicación predeterminada de los archivos de migración, configurar el esquema de la base de datos (también conocido como espacio de tabla), cambiar el prefijo de migración SQL de "V" a lo que queramos y más.

En la configuración siguiente, configuramos la ruta donde se encuentran los archivos de migración y deshabilitamos la limpieza de la base de datos (es decir, eliminar todas las tablas) para evitar el uso accidental en producción.

Listado 4.1  propiedades.de.la aplicación:

spring.flyway.locations=classpath:migrations
spring.flyway.clean-disabled=true

Hay otras propiedades configurables bajo esta clave spring.flywayque podemos usar para ajustar el comportamiento de la biblioteca. Además, podemos consultar la página de documentación de Flyway como referencia.

devolución de llamada de ruta de vuelo

Flyway nos brinda la capacidad de configurar devoluciones de llamadas que se pueden invocar en diferentes etapas del proceso de migración. El mecanismo de devolución de llamada es una forma conveniente de realizar determinadas acciones en diferentes etapas del ciclo de vida de la migración. 

Digamos que tenemos algunos datos predeterminados que queremos generar al iniciar la aplicación. Simplemente podemos crear una AFTER_MIGRATEdevolución de llamada que admita este evento.

Listado 5.1  FlywayDatabaseSeeder.java:

public class FlywayDatabaseSeeder implements Callback {

    @Override
    public boolean supports(Event event, Context context) {
        return event.name().equals(Event.AFTER_MIGRATE.name());
    }
    
    @Override
    public void handle(Event event, Context context) {
        try(var statement = context.getConnection().createStatement()) {

            var ADMIN_EMAIL = "[email protected]";
            
            var checkQuery = "SELECT id FROM users WHERE email = %s"
                    .formatted(ADMIN_EMAIL);
            
            statement.execute(checkQuery);
            ResultSet resultSet = statement.getResultSet();
            resultSet.last();

            //return if the seeder has already been executed
            if(resultSet.getRow() >= 0) return;

            var sql = """
                    INSERT INTO users (email, name) VALUES
                    ('%s', 'Super Admin')
                    """.formatted(ADMIN_EMAIL);
            
            statement.execute(sql);
            
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean canHandleInTransaction(Event event, Context context) {
        return true;
    }

    @Override
    public String getCallbackName() {
        return FlywayDatabaseSeeder.class.getName();
    }
}

En el listado anterior, en supportsel método, declaramos que AFTER_MIGRATEesta devolución de llamada solo debe ejecutarse para el evento, y en handleel método, describimos la lógica para insertar el usuario superadministrador predeterminado si aún no existe.

Antes de eso, debemos registrar la clase de devolución de llamada con Flyway en SpringBoot. Hacemos FlywayMigrationStrategyesto creando un frijol.

Listado 5.2  SpringBootFlywayApplication.java  :

@Bean
public FlywayMigrationStrategy flywayMigrationStrategy() {
	return (flywayOld) -> {

		/*
		 Update the existing autoconfigured Flyway
		 bean to include our callback class
		*/
		Flyway flyway = Flyway.configure()
				.configuration(flywayOld.getConfiguration())
				.callbacks(new FlywayDatabaseSeeder())
				.load();

		flyway.migrate();

	};
}

Hay otros eventos en la enumeración rg.flywaydb.core.api.callback.Event  , podemos configurar Callbackla clase para que los admita. Por ejemplo, podría recibir una devolución de llamada para respaldar el AFTER_MIGRATE_ERRORevento y enviar una notificación de Slack para alertar al ingeniero.

consejos y trucos

Al desarrollar en un entorno local, puede eliminar las entradas de migración de la tabla Flyway_schema_history.

La próxima vez que inicies la aplicación, la migración cuyo historial eliminaste se ejecutará nuevamente. De esta manera, puede corregir errores o actualizar el esquema mientras continúa desarrollando en su máquina local sin eliminar toda la base de datos.

Además, en SpringBoot, puede controlar cuándo Flyway ejecuta scripts de migración al iniciar la aplicación. Por ejemplo, supongamos que no queremos automatizar las migraciones en nuestro entorno local. Podemos hacer lo siguiente:

Listado 6.1  SpringBootFlywayApplication.java:

@Bean
public FlywayMigrationStrategy flywayMigrationStrategy(@Value("${spring.profiles.active}") String activeProfile) {
	return (flywayOld) -> {

		/*
		 Update the existing autoconfigured Flyway
		 bean to include our callback class
		*/
		Flyway flyway = Flyway.configure()
				.configuration(flywayOld.getConfiguration())
				.callbacks(new FlywayDatabaseSeeder())
				.load();

		if(!"local".equalsIgnoreCase(activeProfile)) {
			flyway.migrate();
		}

	};
}

en conclusión

Una de las ventajas de utilizar una herramienta de migración de bases de datos es que hace que el esquema de la base de datos forme parte del código base de la aplicación. Dado que existe un punto de referencia central en la aplicación, es más fácil realizar un seguimiento de los cambios en la base de datos a lo largo del tiempo.

Supongo que te gusta

Origin blog.csdn.net/qq_28245905/article/details/132290264
Recomendado
Clasificación