Kotlin 中的数据库迁移:如何轻松管理模式
在使用 Kotlin 开发时,尤其是在与 JVM 结合的场景下,迟早会遇到在开发人员、测试服务器和生产服务器之间同步数据库结构的问题。手动执行 SQL 脚本会导致不同步和错误。解决方案是——数据库迁移。这是一种对模式变更进行版本控制的自动化方式:创建表、添加列、索引和触发器。
本文将介绍三种适用于 Kotlin 的流行工具:Flyway、Liquibase 以及 Exposed 的内置机制。您将了解如何将它们集成到项目中、编写迁移以及避免典型问题。
Flyway:简单性与版本控制
Flyway 是 JVM 生态系统中最流行的迁移工具。它支持 Kotlin、Java 和 Groovy。工作原理:您编写 SQL 脚本(或 Java/Kotlin 类),Flyway 通过表 flyway_schema_history 跟踪哪些脚本已被应用。
在 Gradle 中集成(Kotlin DSL):
dependencies { implementation("org.flywaydb:flyway-core:9.22.3") // 用于 PostgreSQL implementation("org.flywaydb:flyway-database-postgresql:9.22.3")}迁移示例 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);从 Kotlin 代码启动:
import org.flywaydb.core.Flyway
fun main() { val flyway = Flyway.configure() .dataSource("jdbc:postgresql://localhost:5432/mydb", "user", "pass") .load() flyway.migrate()}优点:
- 最小化配置
- 付费版本支持回滚(undo)
- 适用于任何 SQL
缺点:
- 没有内置的模式验证
- 难以管理分支
Liquibase:灵活性与声明式
Liquibase 提供两种方法:变更可以用 XML、YAML、JSON 或直接使用 SQL 来描述。对于 Kotlin 项目,YAML 格式很方便——它可读性强且易于版本控制。
添加到 Gradle:
dependencies { implementation("org.liquibase:liquibase-core:4.24.0")}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: email从 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