miércoles, 15 de septiembre de 2021

Flyway, r2dbc y spring boot

realizacion en video: https://www.youtube.com/watch?v=lJE5tkSmUPk


Flyway es una herramienta para versionar los cambios en base de datos que sirve para parecido a lo que se hace con git mantener un historial de los cambios en la base de datos y aplicarlos con facilidad.

Para usar flyway con spring lo primero es crear una aplicación de spring para esto nos dirijimos a https://start.spring.io/ ya estando hay vamos a seleccionar un proyecto gradle, con kotlin, en la versión 2.5.4(al momento que hice el tutorial), le vamos a poner el nombre flywaydemo y el package com.example.flywaydemo(si esto cambia solo es cambiar en los ejemplos la ruta de los package), packaging war y versión de java 16.

Luego vamos a dar clic en ADD DEPENDENCIES y vamos a seleccionar las dependencias de Spring Reactive Web(para que podamos trabajar con programación reactiva, flux, monos etc), Spring Data R2DBC como driver reactivo para conectarnos a la base de datos,Flyway Migration y postgresql. tal como se muestra en la imagen

 



En la imagen me faltó agregar postgresql pero agregarlo también.

teniendo escogido todo esto vamos a descargar el proyecto base y abrirlos con nuestro editor favorito de java en mi caso intellij y vamos a crear un archivo docker-compose que nos permita subir la base de datos postgres en docker de manera fácil para esto vamos a crear un archivo en la carpeta del proyecto llamado docker-compose.yml que tenga el siguiente contenido.
version: '3'
services:
postgresdb:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: admin
POSTGRES_DB: flywaydemo


y vamos a correr en la terminal

$docker-compose up -d

esto nos va correr postgres con los valores que tenemos en el archivo y lo va subir listo para usarlo

lo siguiente que vamos a hacer es crear una carpeta configuration dentro de src/main/kotlin/com/example/flywayDemo/configuration/ y dentro creamos un archivo FlywayConfig como clase de kotlin con el siguiente contenido
package com.example.flywayDemo.configuration

import org.flywaydb.core.Flyway
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class FlywayConfig(@Value("\${spring.flyway.url}")private val url: String,
@Value("\${spring.flyway.user}")private val user: String,
@Value("\${spring.flyway.password}")private val password: String,
) {
@Bean(initMethod = "migrate")
fun flyway(): Flyway? = Flyway(Flyway.configure().baselineOnMigrate(true).dataSource(url, user, password))
}


esta clase es para que flyway interactue correctamente con r2dbc y fue sacada de aca https://stackoverflow.com/questions/59553647/how-to-run-flyway-migration-for-reactive-r2dbc-driver-on-sprintboot-stratup

luego entonces vamos a crear un archivo src/main/resources con el nombre application.yml donde vamos a poner la configuracion de nuestra aplicación tanto de flyway como de la conexion a postgres colocando el siguiente contenido
logging:
level:
root: INFO
spring:
r2dbc:
url: 'r2dbc:postgresql://localhost:5432/flywaydemo'
username: 'postgres'
password: 'admin'
pool:
validation-query: 'SELECT 1'

flyway:
url: 'jdbc:postgresql://localhost:5432/flywaydemo'
user: 'postgres'
password: 'admin'
schemas: 'public'
baseline-on-migrate: true


Teniendo esto listo vamos a crear una tabla de prueba para que flyway la cree en la base de datos dentro de la carpeta src/main/resources/db/migration un archivo llamado V20210915082200__init.sql en este caso estamos siguiendo el formato para nombrar el archivo de AÑO MES DIA HORA_MILITAR MINUTO SEGUNDO dos guión bajo <cualquier nombre> . sql, la idea es que con esto podemos saber cuando se hizo cada cambio con la fecha y que flyway pueda ordenar la aplicación de los registros dentro de este archivo vamos a poner la creación de una tabla simple.
CREATE TABLE public.demouser
(
"id" BIGSERIAL PRIMARY KEY,
"username" text NOT NULL,
"password" text NOT NULL,
"created_at" timestamptz NOT NULL DEFAULT now(),
"last_updated_at" timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS demouser_userName_index ON public.demouser ("username");


en esta misma carpeta también vamos a colocar otro archivo llamado V20210915083000__registro.sql con el siguiente contenido
insert into public.demouser(username,password) values('sebastian','miclave')


teniendo esto listo ya no es sino correr la aplicación y conectarnos a la database que estamos corriendo con docker para revisar en este caso yo me voy a conectar usando DBeaver con las credenciales que se definieron en el archivo docker-compose

 


y correr un script como este

select * from public.demouser;

Con esto verificamos que flyway se encargó por nosotros de crear la tabla e insertar el registro, los cambios futuros en la base de datos se crean como archivos independientes respetando el formato y haciendo las modificaciones en la base de datos como haríamos en la consola de postgresql de esta manera mantenemos los cambios versionados.

Solo una nota más si es posible recomiendo que los nombres de propiedades en la tabla no tengan mayúsculas para evitar problemas tengo entendido que tambien tiene solucion pero entra en juego otra configuracion para el formatter