Migraciones de bases de datos en Kotlin: cómo gestionar el esquema sin dolor
Al desarrollar en Kotlin, especialmente en conjunto con JVM, tarde o temprano surge la tarea de sincronizar la estructura de la base de datos entre desarrolladores, servidores de prueba y producción. La ejecución manual de scripts SQL provoca desincronización y errores. La solución son las migraciones de bases de datos. Es una forma automatizada de versionar los cambios del esquema: creación de tablas, adición de columnas, índices y disparadores.
En este artículo analizaremos tres herramientas populares para Kotlin: Flyway, Liquibase y el mecanismo integrado de Exposed. Aprenderá cómo integrarlas en su proyecto, escribir migraciones y evitar problemas típicos.
Flyway: simplicidad y versionado
Flyway es la herramienta de migraciones más popular en el ecosistema JVM. Soporta Kotlin, Java y Groovy. Su principio de funcionamiento: usted escribe scripts SQL (o clases Java/Kotlin), y Flyway rastrea cuáles ya se han aplicado mediante la tabla flyway_schema_history.
Conexión en Gradle (Kotlin DSL):
dependencies { implementation("org.flywaydb:flyway-core:9.22.3") // para PostgreSQL implementation("org.flywaydb:flyway-database-postgresql:9.22.3")}Ejemplo de migración V1__create_users.sql:
CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, email VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT NOW());
CREATE INDEX idx_users_email ON users(email);Ejecución desde código Kotlin:
import org.flywaydb.core.Flyway
fun main() { val flyway = Flyway.configure() .dataSource("jdbc:postgresql://localhost:5432/mydb", "user", "pass") .load() flyway.migrate()}Ventajas:
- Configuración mínima
- Soporte de reversiones (undo) en la versión de pago
- Funciona con cualquier SQL
Desventajas:
- Sin validación de esquema integrada
- Difícil de gestionar la ramificación
Liquibase: flexibilidad y declaratividad
Liquibase ofrece dos enfoques: los cambios se pueden describir en XML, YAML, JSON o directamente en SQL. Para proyectos Kotlin, el formato YAML es conveniente: es legible y fácil de versionar.
Adición en Gradle:
dependencies { implementation("org.liquibase:liquibase-core:4.24.0")}Ejemplo de archivo changelog db.changelog-master.yaml:
databaseChangeLog: - changeSet: id: 1 author: developer changes: - createTable: tableName: users columns: - column: name: id type: BIGINT autoIncrement: true constraints: primaryKey: true - column: name: username type: VARCHAR(50) constraints: nullable: false unique: true - column: name: email type: VARCHAR(100) - createIndex: indexName: idx_users_email tableName: users columns: - column: name: emailEjecución desde Kotlin:
import liquibase.Liquibaseimport liquibase.database.jvm.JdbcConnectionimport liquibase.resource.ClassLoaderResourceAccessorimport java.sql.DriverManager
fun runMigrations() { val connection = DriverManager.getConnection( "jdbc:postgresql://localhost:5432/mydb", "user", "pass" ) val database = DatabaseFactory.getInstance() .findCorrectDatabaseImplementation(JdbcConnection(connection)) val liquibase = Liquibase("db.changelog-mas También en la biblioteca
Trabajo con Kafka en Kotlin: bibliotecas, configuración y ejemplos
Monitoreo de aplicaciones PHP: herramientas y bibliotecas para el seguimiento del rendimiento
vitest para TypeScript: guía completa con ejemplos
Contenedor de Inyección de Dependencias para Swift (iOS/macOS): Swinject
ORM para C++: comparación y ejemplos de uso