この記事を書くモチベーション
現在担当しているKotilnで書かれたプロダクトにDomaを新規に採用しようとしています。
しかし、Kotlinの理解がまだ浅くEnumのドメインクラス化に苦戦してしまいました。
最終的には実現できたのですが(簡単な設定だったけど時間がかかってしまいましたorz)、おそらく同じように苦戦している人もいると思い、そんな人達に向けてQiitaに解説記事を投稿しておきます。1
何はともあれサンプルコード 〜コード解説〜
Enumのドメインクラス
package sample
import org.seasar.doma.Domain
@Domain(valueType = String::class, accessorMethod = "getCode", factoryMethod = "of")
// if you use enum without additional value and also do not use its value for database, you can do like this.
//@Domain(valueType = String::class, accessorMethod = "name", factoryMethod = "valueOf")
enum class Gender(val code: String) {
MALE("0"),
FEMALE("1");
companion object {
@JvmStatic // doma requires JvmStatic annotation for factory method
fun of(code: String): Gender =
values().firstOrNull { it.code == code } ?: throw IllegalArgumentException("${Gender::class.simpleName} does not have such code => $code")
}
}
ポイントは@Domain
アノテーションのaccessorMethod
とfactoryMethod
です。
accessorMethod
Kotlinをcompileして生成されるJavaのclassでは、kotlinのプロパティにget
のプレフィックスをつけたgetterが生えるので、その名前に合わせてaccessorMethod
をつけています。
factoryMethod
@Domain
のfactoryMethod
にはJavaのstaticなメソッドを指定します。
Kotlinで同じものに該当するのはコンパニオンオブジェクトですが、コンパニオンオブジェクトはそのままだと対象クラスにCompanion
という名前で内部クラスを生成し、そのクラス経由でアクセスできるようになります。
e.g.) SomeClass.Companion.staticMethod()
しかし、Domaはそんなことを知らないのでfactoryMethod
で指定されたメソッドを探しに行きますが、Companion
経由でしかアクセスできない状態なのでコンパイルエラーになります。
そのため、staticメソッドのように見えるために@JvmStatic
をつけて上げる必要があります。
最後に
簡単な内容でしたが、以上でKotlinでもEnumのドメインクラスが使えるようになりました。
この記事で、本質的ではないところで時間の浪費をする人が減ってくれるといいな…
doma kotlin-sample
ちなみに、domaのkotlin-sampleにもPRを送りマージして頂きました。
送ってすぐにマージして頂けました、感謝です。
以上です。
-
Qiitaやはてなブログなどに投稿しておけば検索にHITしやすいはず ↩