0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kotlin の Exposed と Flyway で実現するシームレスなデータベースマイグレーション:Prisma ライクな開発体験

Last updated at Posted at 2025-04-30

概要

この記事では、Kotlin で Exposed と Flyway を使用して、Prisma に似たデータベーススキーマ管理とマイグレーションの開発体験を作る方法を紹介します。

必要なもの

  • Exposed: Kotlin 用の JetBrains 製 ORM フレームワーク(org.jetbrains.exposed:exposed-coreorg.jetbrains.exposed:exposed-migrationなどの依存関係)
  • Flyway: データベースバージョン管理用のマイグレーションツール(org.flywaydb:flyway-coreなどの依存関係)
  • データベースドライバ: 選択したデータベース用の JDBC ドライバ

1. テーブルの定義

Exposed を使うと、データベーススキーマを Kotlin オブジェクトとして定義でき、コンパイル時の安全性と IDE 支援が得られます。以下は顧客テーブルの定義例です:

// ...
import org.jetbrains.exposed.dao.id.UUIDTable
// ...

object CustomerTable : Table("customers") {
    val id = integer("id").autoIncrement()
    val name = text("name")
    val email = text("email")

    override val primaryKey = PrimaryKey(id)
}

詳しくはExposed のドキュメントをご覧ください。

2. 必要なマイグレーションの確認

マイグレーションを適用する前に、データベースをテーブル定義と同期するために必要な SQL ステートメントを確認すると便利です。これは特に開発中にスキーマ変更の影響を確認するのに役立ちます:

// ...
import MigrationUtils
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.StdOutSqlLogger
import org.jetbrains.exposed.sql.addLogger
import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.LoggerFactory
// ...


fun checkForRequiredMigrations() {
    Database.connect(
        ...
    )

    transaction {
        addLogger(StdOutSqlLogger)

        val statements = MigrationUtils.statementsRequiredForDatabaseMigration(
            tables = arrayOf(CustomerTable, ...) // ここに全てのテーブルを追加
        )

        if (statements.isNotEmpty()) {
            val combinedStatements = statements.joinToString("\n")

            println("\n=== データベースマイグレーションが必要です! ===\n$combinedStatements\n=== マイグレーション終了 ===")
        }
    }
}

この関数は以下を行います:

  1. Exposed のテーブル定義と実際のデータベーススキーマを比較
  2. データベースを同期するために必要な SQL ステートメントを生成
  3. レビュー用に出力

例えば、CustomerTableを追加した後にこのチェックを実行すると、次のような出力が表示されます:

=== データベースマイグレーションが必要です! ===
CREATE TABLE IF NOT EXISTS customers (id SERIAL PRIMARY KEY, "name" TEXT NOT NULL, email TEXT NOT NULL)
CREATE SEQUENCE IF NOT EXISTS customers_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807
=== マイグレーション終了 ===

この出力が表示されたら、src/main/resources/db/migrationに有効な Flyway マイグレーションファイル名で新しいファイルを作成してください。

V1__add_customer_table.sql
CREATE TABLE IF NOT EXISTS customers (id SERIAL PRIMARY KEY, "name" TEXT NOT NULL, email TEXT NOT NULL)
CREATE SEQUENCE IF NOT EXISTS customers_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807

詳しくはFlyway のドキュメントをご覧ください。

3. Flyway によるマイグレーションの適用

Exposed はマイグレーション用の SQL を生成できますが、Flyway はそれらのマイグレーションをバージョン管理し適用する堅牢な方法を提供します:

// ...
import org.flywaydb.core.Flyway
// ...

fun applyMigrations() {
    Flyway.configure().dataSource(
        ...
    ).load().migrate()
}

この関数は以下を行います:

  1. デフォルトの場所(db/migration)からマイグレーションスクリプトを見つける
  2. 保留中のマイグレーションを順番に適用する
  3. Flyway のメタデータテーブルでマイグレーション履歴を追跡する

こちらもFlyway のドキュメントで詳細を確認してください。

おまけ:マイグレーションファイルの自動生成

マイグレーションファイルを自動生成することもできます:

MigrationUtils.generateMigrationScript(
    tables = arrayOf(CustomerTable, OrderTable, ProductTable),
    "./src/main/resources/db/migration",
    "V1__add_customer_table"
)

これにより Flyway のマイグレーションディレクトリに SQL ファイルが作成されます。

まとめ

ExposedとFlywayを組み合わせることで、型安全なスキーマ定義とシンプルで確実なマイグレーション管理が可能になります。これにより、Prismaのような直感的な開発体験をKotlinでも実現でき、データベーススキーマの変更を簡潔で効率的に進めることができます。

ほなまた!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?