Migraciones de bases de datos en Kotlin: Guía completa de herramientas y enfoques
La gestión de cambios en el esquema de la base de datos es una de las tareas clave en el desarrollo de cualquier aplicación. En el ecosistema de Kotlin existen varias soluciones maduras que permiten automatizar este proceso. En este artículo analizaremos tres enfoques principales: las herramientas integradas del ORM Exposed, el clásico Flyway y el potente Liquibase. Aprenderás cómo integrarlos en un proyecto de Kotlin y qué herramienta elegir según tus necesidades específicas.
1. ¿Por qué son necesarias las migraciones?
La ejecución manual de scripts SQL en diferentes entornos (entorno de desarrollo local, staging, producción) conduce inevitablemente a la desincronización del esquema. Las migraciones resuelven este problema proporcionando:
- Versionado de los cambios en la base de datos
- Aplicación automática de nuevos scripts al iniciar la aplicación
- Posibilidad de revertir (rollback) a una versión anterior
- Trabajo en equipo sin conflictos de esquema
2. Exposed: Soporte nativo de migraciones
Exposed es un ORM ligero de JetBrains, escrito en Kotlin. A partir de la versión 0.41.0, la biblioteca proporciona su propio mecanismo de migraciones que encaja perfectamente en el ecosistema de Kotlin.
Instalación
// build.gradle.ktsimplementation("org.jetbrains.exposed:exposed-core:0.55.0")implementation("org.jetbrains.exposed:exposed-dao:0.55.0")implementation("org.jetbrains.exposed:exposed-migrations:0.55.0")Creación de una migración
Cada migración es una clase que hereda de VoidDatabaseMigration:
import org.jetbrains.exposed.sql.transactions.transactionimport org.jetbrains.exposed.sql.SchemaUtilsimport org.jetbrains.exposed.sql.Tableimport org.jetbrains.exposed.migrations.VoidDatabaseMigration
object Users : Table() { val id = integer("id").autoIncrement() val name = varchar("name", 255) override val primaryKey = PrimaryKey(id)}
class V1__CreateUsersTable : VoidDatabaseMigration() { override fun migrate() { transaction { SchemaUtils.create(Users) } }}
class V2__AddEmailColumn : VoidDatabaseMigration() { override fun migrate() { transaction { SchemaUtils.addColumn(Users, Users.varchar("email", 255)) } }}Ejecución de migraciones
import org.jetbrains.exposed.migrations.ExposedMigrationUtilsimport javax.sql.DataSource
fun runMigrations(dataSource: DataSource) { ExposedMigrationUtils.runMigrations( dataSource = dataSource, migrationsPackage = "com.example.migrations" )}Ventajas: completamente en estilo Kotlin, sin archivos SQL, nombres de columnas tipados.
Desventajas: vinculación a Exposed, sin rastreador visual, sin rollback "de fábrica".
3. Flyway: Simplicidad y fiabilidad
Flyway es la herramienta más popular para migraciones en el mundo JVM. Funciona con cualquier base de datos y no depende del ORM. En Kotlin se utiliza a través del SDK oficial o el plugin de Gradle.
Configuración
// build.gradle.ktsimplementation("org.flywaydb:flyway-core:10.20.0")// Para PostgreSQL añade el driver:implementation("org.postgresql:postgresql:42.7.4")Estructura de las migraciones
Flyway utiliza archivos SQL con un nombre específico:
db/migration/ V1__create_users.sql V2__add_email_column.sql V3__add_role_column.sqlEjemplo de migración SQL (V1__create_users.sql)
CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE);Integración con Kotlin
import org.flywaydb.core.Flywayimport javax.sql.DataSou También en la biblioteca
Criptografía en Java: cifrado y hash de datos
Configuración de aplicaciones en C++: bibliotecas y herramientas para una configuración flexible
Envío de email en Kotlin: bibliotecas, ejemplos y configuración SMTP
Procesamiento de imágenes en C++: bibliotecas CImg, OpenCV y stb_image