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

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

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

Начать курс

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

Управление изменениями схемы базы данных — одна из ключевых задач при разработке любого приложения. В экосистеме Kotlin существует несколько зрелых решений, которые позволяют автоматизировать этот процесс. В этой статье мы разберем три основных подхода: встроенные средства ORM Exposed, классический Flyway и мощный Liquibase. Вы узнаете, как интегрировать их в проект на Kotlin и какой инструмент выбрать под конкретные задачи.

1. Зачем нужны миграции?

Ручное выполнение SQL-скриптов на разных окружениях (локальная среда разработки, стейджинг, продакшн) неизбежно приводит к рассинхронизации схемы. Миграции решают эту проблему, предоставляя:

  • Версионирование изменений базы данных
  • Автоматическое применение новых скриптов при старте приложения
  • Возможность отката (rollback) до предыдущей версии
  • Командную работу без конфликтов схемы

2. Exposed: Нативная поддержка миграций

Exposed — это легковесная ORM от JetBrains, написанная на Kotlin. Начиная с версии 0.41.0, библиотека предоставляет собственный механизм миграций, который идеально вписывается в экосистему Kotlin.

Установка

// build.gradle.kts
implementation("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")

Создание миграции

Каждая миграция — это класс, наследующий от VoidDatabaseMigration:

import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.Table
import 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))
        }
    }
}

Запуск миграций

import org.jetbrains.exposed.migrations.ExposedMigrationUtils
import javax.sql.DataSource

fun runMigrations(dataSource: DataSource) {
    ExposedMigrationUtils.runMigrations(
        dataSource = dataSource,
        migrationsPackage = "com.example.migrations"
    )
}

Плюсы: полностью Kotlin-стиль, нет SQL-файлов, типизированные имена колонок.
Минусы: привязка к Exposed, нет визуального трекера, отсутствие rollback "из коробки".

3. Flyway: Простота и надёжность

Flyway — самый популярный инструмент для миграций в JVM-мире. Он работает с любыми базами данных и не зависит от ORM. В Kotlin его используют через официальный SDK или Gradle-плагин.

Подключение

// build.gradle.kts
implementation("org.flywaydb:flyway-core:10.20.0")
// Для PostgreSQL добавьте драйвер:
implementation("org.postgresql:postgresql:42.7.4")

Структура миграций

Flyway использует SQL-файлы с определённым именованием:

db/migration/
   V1__create_users.sql
   V2__add_email_column.sql
   V3__add_role_column.sql

Пример SQL-миграции (V1__create_users.sql)

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE
);

Интеграция с Kotlin

import org.flywaydb.core.Flyway
import javax.sql.DataSource

fun migrateDatabase(dataSource: DataSource) {
    val flyway = Flyway.configure()
        .dataSource(dataSource)
        .locations("classpath:db/migration")
        .load()
    flyway.migrate()
}

Плюсы: простота, поддержка откатов (через V1__...__description.sql и U1__...sql), интеграция с CI/CD.
Минусы: SQL-файлы вне Kotlin-кода, сложно рефакторить имена колонок.

4. Liquib

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