KotlinのExposedについて

採用はこちら

Exposedは、Kotlinからデータベースを操作するためのライブラリで、Kotlinの言語機能を活かしたSQL DSLと軽量ORM機能を提供します。

このライブラリは JetBrains が開発しており、Kotlinバックエンド開発では代表的なデータベースアクセスライブラリの一つです。

JavaエコシステムではHibernateやJPAがよく使われますが、Exposedはそれらとは異なり、SQLに近い感覚で安全にクエリを書ける設計が特徴です。

目次

Exposedの概要

ExposedはKotlinでデータベース操作を行うためのライブラリで、以下の特徴を持っています。

主な特徴

  • Kotlin DSLでSQLを構築できる
  • 型安全なクエリ記述
  • JDBCおよびR2DBCに対応
  • 軽量なORM(DAO API)を提供
  • トランザクション管理機能
  • 複数のRDBMSに対応

対応している主なデータベース

  • PostgreSQL
  • MySQL
  • MariaDB
  • SQLite
  • H2
  • Oracle
  • Microsoft SQL Server

つまりExposedは「Kotlinで安全にSQLを書くためのデータベースライブラリ」と言えます。

Exposedの2つのAPI

Exposedには大きく分けて2つの利用方法があります。

  1. DSL API
  2. DAO API

それぞれ用途が異なります。

DSL API

DSL APIは、KotlinのDSL構文を利用してSQLを構築する方法です。

SQLに近い形で書くことができ、柔軟なクエリを作成できます。

Users
    .selectAll()
    .where { Users.age greater 20 }

このコードは次のSQLに相当します。

SELECT * FROM users
WHERE age > 20;

DSL APIの特徴

  • SQLに近い表現
  • 柔軟なクエリ
  • パフォーマンス制御しやすい
  • 型安全

実務ではDSL APIを中心に使用するケースが多いです。

DAO API

DAO APIは、ORMのようにEntityクラスを通してデータベースを操作する方法です。

Entity例

class User(id: EntityID<Int>) : IntEntity(id) {

    companion object : IntEntityClass<User>(Users)

    var name by Users.name
    var age by Users.age
}

取得例

User.find { Users.age greater 20 }

新規作成

User.new {
    name = "Taro"
    age = 25
}

DAO APIはORMに近い書き方になりますが、DSL APIより柔軟性はやや低くなります

また、DAO APIはJDBC接続でのみ利用可能です。

Exposedの基本構造

Exposedでは次の要素を中心にデータベース操作を行います。

要素役割
Tableテーブル定義
Columnカラム定義
Transactionトランザクション管理
DSLSQLクエリ
DAOEntity操作

テーブル定義

Exposedではテーブル構造をKotlinクラスで定義します。

object Users : Table() {

    val id = integer("id").autoIncrement()
    val name = varchar("name", 50)
    val age = integer("age")

    override val primaryKey = PrimaryKey(id)
}

このコードは次のSQLテーブルを表します。

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50),
  age INT
);

データベース接続

データベース接続は Database.connect() を使用します。

Database.connect(
    url = "jdbc:h2:mem:test",
    driver = "org.h2.Driver"
)

JDBC接続の場合、通常はトランザクションブロック内で操作を行います。

transaction {

    // DB操作

}

データ挿入(INSERT)

データを追加する場合は insert を使用します。

transaction {

    Users.insert {
        it[name] = "Taro"
        it[age] = 25
    }

}

SQL

INSERT INTO users (name, age)
VALUES ('Taro', 25);

データ取得(SELECT)

全件取得

transaction {

    Users.selectAll().forEach {
        println(it[Users.name])
    }

}

条件検索

Users
    .selectAll()
    .where { Users.age greater 20 }

データ更新(UPDATE)

transaction {

    Users.update({ Users.id eq 1 }) {
        it[age] = 30
    }

}

SQL

UPDATE users
SET age = 30
WHERE id = 1;

データ削除(DELETE)

transaction {

    Users.deleteWhere { Users.id eq 1 }

}

SQL

DELETE FROM users
WHERE id = 1;

JOINクエリ

ExposedではJOINもDSLで記述できます。

(Users innerJoin Orders)
    .selectAll()

SQL

SELECT *
FROM users
INNER JOIN orders
ON users.id = orders.user_id;

Exposedのメリット

Kotlin DSLによる型安全

ExposedはKotlin DSLでクエリを書くため、コンパイル時に型チェックが行われます。

そのため

  • カラム名のミス
  • 型不一致

などを防ぐことができます。

SQLに近い記述

DSL APIはSQL構造に近いため、

  • クエリの可読性
  • SQL理解

を保ったままコードを書くことができます。

軽量でシンプル

HibernateなどのフルORMと比較すると、

  • 設定が少ない
  • 学習コストが低い
  • 動作が軽い

というメリットがあります。

Exposedのデメリット

フルORMではない

Hibernateのような機能は限定的です。

例えば

  • 自動JOIN
  • キャッシュ
  • 高度なエンティティ管理

などは弱い傾向があります。

エコシステムが小さい

JPAと比べると

  • 情報量
  • サンプル
  • 外部ライブラリ

はまだ少なめです。

Kotlinバックエンドでの典型構成

Kotlinサーバー開発では次の構成がよく見られます。

Ktor
↓
Exposed
↓
PostgreSQL

Exposedは特にKotlinネイティブなフレームワークと相性が良いです。

他のORMとの違い

技術特徴
JPAJava標準ORM
Hibernate高機能ORM
MyBatisSQL中心
ExposedKotlin DSL型ORM

ExposedはSQL DSL + 軽量ORMという中間的な位置にあります。

Exposedが向いているケース

次のようなプロジェクトではExposedが適しています。

  • Kotlinバックエンド開発
  • SQLを明示的に管理したい
  • ORMの自動生成に頼りすぎたくない
  • Ktorベースのサーバー

まとめ

ExposedはKotlin向けのデータベースライブラリで、

  • SQL DSL
  • 軽量ORM
  • 型安全

という特徴を持っています。

JavaのORMとは違い、SQLの可視性と柔軟性を重視した設計が特徴です。

そのため、Kotlinバックエンド開発ではKtor + Exposed + PostgreSQLのような構成で使われることが多く、Kotlinネイティブなデータアクセスライブラリとして広く利用されています。

以上、KotlinのExposedについてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次