ExposedでenumのリストをStringにシリアライズしてカラムにいれる

投稿日:

カテゴリ: 技術メモ

使い所

  • ユーザーのロールとかをリストで扱いたいけどテーブルを正規化する気力がないとき
  • 対応していないSQLドライバでarrayっぽいことをしたいとき

やりかた

いいか悪いかは置いておいて、こんな感じの拡張関数を定義するといい感じに動く
textのカラムを用意してカンマ区切りでenumの名前を突っ込む

operator fun <T, E : Enum<E>> UpdateBuilder<T>.set(column: Column<String>, value: List<E>): Unit =
    set(column, value.joinToString(","))

inline fun <reified T : Enum<T>> ResultRow.getEnums(expression: Expression<String>): List<T> =
    get(expression).split(",").map { enumValueOf(it) }

使うとき

enum class MyEnum {
    Value1,
    Value2,
    Value3
}

object MyTable : LongIdTable("my_table", "id") {
    val enums = text("enums")
}

fun insert() = transaction {
    MyTable.insert {
        it[enums] = listOf(MyEnum.Value1, MyEnum.Value3)
    }
}

fun select(id: Long): List<MyEnum> = transaction {
    MyTable.selectAll()
        .where { MyTable.id eq id }
        .map {
            it.getEnums<MyEnum>(MyTable.enums)
        }
        .singleOrNull() ?: emptyList()
}

RoomのTypeConverters的なことができると本当は良さそう