LoginSignup
10
2

More than 1 year has passed since last update.

ExposedのDB周りの実装について(Kotlin × Spring Boot

Last updated at Posted at 2023-04-06

弊社は自社サービスの開発で現在Kotlin言語を利用してSpringBootでのアプリケーション開発を行っています。
なかなか文献が少ない構成ではあるので色々公開していきたいと思ってます。

今回はテーブル定義とdao周りの実装です

前提

言語はkotlin
DBはPostgres
org.jetbrains.exposedの0.38.2を利用。

以下の構成を想定しての実装解説となります
スクリーンショット 2022-11-30 20.33.36.png

必要なパッケージ

以下のパッケージをgradleで定義

implementation("org.jetbrains.exposed", "exposed-core", "0.38.2")
implementation("org.jetbrains.exposed", "exposed-dao", "0.38.2")
implementation("org.jetbrains.exposed", "exposed-jdbc", "0.38.2")
implementation("org.jetbrains.exposed", "exposed-jodatime", "0.38.2")
implementation("org.jetbrains.exposed", "exposed-java-time", "0.38.2")
implementation("org.jetbrains.exposed", "exposed-spring-boot-starter", "0.38.2")
implementation("org.jetbrains.exposed", "spring-transaction", "0.38.2")

テーブル定義の実装

import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.jodatime.date
import org.jetbrains.exposed.sql.jodatime.datetime

object Users: IntIdTable("users") {
    var name = varchar("name", 50)
    var address = varchar("address", 255).nullable()
    var isActive = bool("is_active").default(false)
    var enteredOn = date("entered_on")
    var createdAt = datetime("created_at")
}
import org.jetbrains.exposed.dao.id.IntIdTable

object Orders: IntIdTable("orders") {
    var user = reference("user_id", Users)
    var code = integer("code")
}

org.jetbrains.exposed.sql.Table クラスに定義されているものを利用できます

また、datetimeやdateについては別パッケージとなっているようです

null / not nullの使い分けについてはどの型であっても .nullable() をつけてあげることで定義可能

リレーション表現については、1:1以上については reference を利用する形となり、
本記事では触れてませんが、1:0以上については optReference を利用します

DAOクラスの実装

import org.jetbrains.exposed.dao.IntEntity
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.dao.id.EntityID

class User(
        id: EntityID<Int>
): IntEntity(id) {
    companion object: IntEntityClass<User>(Users)
    var name by Users.name
    var address by Users.address
    var isActive by Users.isActive
    var enteredOn by Users.enteredOn
    var createdAt by Users.createdAt
}
import org.jetbrains.exposed.dao.IntEntity
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.dao.id.EntityID

class Order(
        id: EntityID<Int>
): IntEntity(id) {
    companion object: IntEntityClass<Order>(Orders)
    var user by User referencedOn Orders.user
    var code by Orders.code
}

DAO側クラスについては基本的にはテーブルクラスのフィールドを見ているだけになります

リレーション表現については、1:1以上については reference を利用する形となり、
本記事では触れてませんが、1:0以上については optReference を利用します

こちらで触れたリレーション表現の仕方については
referenceは referencedOn
optReferenceは optionalReferencedOn
を利用することになります

最後に

テーブル定義とDAO定義それぞれやらないといけないので若干めんどくさいところもあるんですが、このようにしとくことによって使うときにコードがスリムになり可読性が向上するので是非やっといたほうが良いかなと思います。

また、かんたんなデータ取得はDAO形式、少し凝ったことをやりたくなったらDSLで書くなど逃げ道も用意できるので個人的には嬉しい感じ(もちろんビジネスロジック上で使い分けちゃうと良くないので隠蔽してあげる必要はあると思いますが)

せっかくテーブル定義があるのだから、マイグレーションもやっちゃいたいなと思ってましたが、現在Flyway使ってしまってます。
どうやらExposedでもできるようなので、今度是非試してみたいと思います

10
2
2

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
10
2