Version v0.18 of the documentation is no longer actively maintained. The site that you are currently viewing is an archived snapshot. For up-to-date documentation, see the latest version.

Overview

サーバーサイドKotlinのためのシンプルでパワフルなSQLマッパー

Komapperとは?

KomapperはKotlin 1.5.31 以上に対応したサーバーサイド向けのSQLマッピングライブラリーです。

Komapperにはいくつかの強みがあります。

  • JDBCとR2DBCのサポート
  • コンパイル時のコード生成
  • イミュータブルなクエリ
  • Value Classのサポート
  • Spring Bootのサポート

JDBCとR2DBCのサポート

Komapperは JDBC もしくは R2DBC を用いてデータベースにアクセスできます。

KomapperはKotlinコルーチンの機能を活用することでJDBCとR2DBCのどちらを使ったとしてもほとんど同じプログラミングモデルを可能にしています。

例えば、JDBCを用いるコードは次のように書けます。

fun main() {
    // create a Database instance
    val db = JdbcDatabase.create("jdbc:h2:mem:example;DB_CLOSE_DELAY=-1")

    // get a metamodel
    val a = AddressDef.meta

    // execute simple CRUD operations in a transaction
    db.withTransaction {
        // create a schema
        db.runQuery {
            SchemaDsl.create(a)
        }

        // INSERT
        val newAddress = db.runQuery {
            EntityDsl.insert(a).single(Address(street = "street A"))
        }

        // SELECT
        val address1 = db.runQuery {
            EntityDsl.from(a).where { a.id eq newAddress.id }.first()
        }
    }
}

一方でR2DBCを使うコードは次のように書けます。(上述のJDBC版との違いがわかるでしょうか?)

fun main() = runBlocking {
    // create a Database instance
    val db = R2dbcDatabase.create("r2dbc:h2:mem:///example;DB_CLOSE_DELAY=-1")

    // get a metamodel
    val a = AddressDef.meta

    // execute simple CRUD operations in a transaction
    db.withTransaction {
        // create a schema
        db.runQuery {
            SchemaDsl.create(a)
        }

        // INSERT
        val newAddress = db.runQuery {
            EntityDsl.insert(a).single(Address(street = "street A"))
        }

        // SELECT
        val address1 = db.runQuery {
            EntityDsl.from(a).where { a.id eq newAddress.id }.first()
        }
    }
}

動作する完全なコードについては komapper-examples リポジトリ直下のconsole-jdbcとconsole-r2dbcのサブプロジェクトを参照ください。

コンパイル時のコード生成

Komapperは Kotlin Symbol Processing API を使ってコンパイル時にデータベースアクセスに必要なメタモデル(テーブルやカラムの情報)をKotlinのソースコードとして生成します。

この仕組みによりKomapperは実行時にリフレクションを用いたりデータベースからメタデータを読み取ったりする必要がありません。 そのため実行時の信頼性とパフォーマンスが向上します。

コード生成はアノテーションの読み取りによって行われます。 例えば、AddressクラスをADDRESSテーブルにマッピングさせる場合次のように記述できます。

data class Address(
    val id: Int,
    val street: String,
    val version: Int
)

@KomapperEntityDef(Address::class)
data class AddressDef(
    @KomapperId val id: Nothing,
    @KomapperVersion val version: Nothing,
) {
    companion object
}

また、生成されたメタモデルを使ってタイプセーフにクエリを組み立てられます。

// get a generated metamodel
val a = AddressDef.meta

// define a query
val query = EntityDsl.from(e).where { a.street eq "STREET 101" }.orderBy(a.id)

イミュータブルなクエリ

Komapperのクエリは実質的にイミュータブルです。 状態の共有に伴う不具合を心配することなく安全に再利用できます。

// get a generated metamodel
val a = AddressDef.meta

// define queries
val query1 = EntityDsl.from(a)
val query2 = query1.where { a.id eq 1 }
val query3 = query2.where { or { a.id eq 2 } }.orderBy(a.street)

// issue "select * from address"
db.runQuery { query1 }
// issue "select * from address where id = 1"
db.runQuery { query2 }
// issue "select * from address where id = 1 or id = 2 order by street"
db.runQuery { query3 }

Value Classのサポート

Kotlin 1.5から導入されたValue Classをエンティティクラスのプロパティとして利用できます。 利用に当たって特別な設定は不要です。

@JvmInline
value class Age(val value: Int)

data class Employee(val id: Int = 0, val name: String, val age: Age)

@KomapperEntityDef(Employee::class)
data class EmployeeDef(@KomapperId @KomapperAutoIncrement val id: Nothing) {
    companion object
}

Spring Bootのサポート

KomapperはSpring Bootとの組み合わせを容易にするstarterを提供します。

例えば、JDBCを使ったデータアクセスをSpring Bootと組み合わせて行いたい場合、 Gradleのdependenciesブロックに次のような設定をするだけで必要なライブラリの依存性が解決されSpring Boot管理のデータソースやトランザクションと連動します。

val komapperVersion: String by project

dependencies {
    implementation("org.komapper:komapper-spring-boot-starter-jdbc:$komapperVersion")
    implementation("org.komapper:komapper-dialect-h2-jdbc:$komapperVersion")
}

動作する完全なコードについては komapper-examples リポジトリ直下のspring-boot-jdbcとspring-boot-r2dbcのサブプロジェクトを参照ください。

サポートするデータベース

現在、下記の4つのデータベースをサポートしています。

データベース バージョン JDBC R2DBC
H2 Database Engine 1.4.200 v v
MariaDB 10.6 v v
MySQL 8.0 v v
PostgreSQL 13.0 v v

バージョンはサポートする最小バージョンを表していますが、より小さいバージョンでも動作することがあります。

次に見るべきドキュメント

最終更新 September 23, 2021 : Change roadmap (8bd8d6e)