Миграции баз данных в Kotlin: инструменты и практические примеры

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Миграции баз данных в 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.Liquibase
import liquibase.database.jvm.JdbcConnection
import liquibase.resource.ClassLoaderResourceAccessor
import 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-master.yaml", ClassLoaderResourceAccessor(), database)
    liquibase.update("")
}

Плюсы:

  • Поддержка rollback по умолчанию
  • Контексты (dev, prod) и precondition
  • Генерация diff между схемами

Минусы:

  • Более сложный синтаксис
  • Медленнее Flyway на больших проектах

Exposed: миграции без ORM-оверхеда

Exposed — это легковесная ORM для Kotlin от JetBrains. В её состав входит модуль exposed-migrations, который позволяет описывать изменения схемы прямо на Kotlin, без SQL.

Подключение:

dependencies {
    implementation("org.jetbrains.exposed:exposed-core:0                    

Рекомендаций