[Kotlin] KomapperでEmbedded Valueをサポートするか検討
Embedded ValueとはP of EAAの用語。
Spring Data JDBCでは対応されている。
Hibernateも。
Komapperでの実現案。KomapperEmbedded
アノテーションを導入する。
data class PersonInfo(
val name: String,
val age: Int
)
@KomapperEntity
data class Person(
@KomapperId @KomapperAutoIncrement
val id: Int = 0,
@KomapperEmbedded
val info: PersonInfo
)
組み込まれる側に@KomapperId
や@KomapperVersion
等を付けるのはサポート外としたい。それをサポートすると実装する側も利用する側も大変すぎる。プレーンなValue Objectのまま使いたいニーズの方が強いのでないか?
ただ複合主キーをEmbedded Valueで表現したいとなるとKomapperEmbedded
アノテーションとは別にKomapperEmbeddedId
アノテーションが必要か?
data class PersonId(
val id1: String,
val id2: Int
)
data class PersonInfo(
val name: String,
val age: Int
)
@KomapperEntity
data class Person(
@KomapperEmbeddedId
val id: PersonId,
@KomapperEmbedded
val info: PersonInfo
)
クエリを書くときはEmbedded Valueの末端のプロパティに対して条件を指定できるようにする。そういうメタモデルを作らないといけない。
val p = Meta.persion
val query = QueryDsl.from(p).where { p.info.name eq "Jhon" }
クエリのselect
にEmbedded Valueのプロパティを指定してEmbedded Valueのインスタンスを直接取得可能とするかは要検討。
val p = Meta.persion
val query: Query<List<PersonInfo>> = QueryDsl.from(p).where { p.info.name eq "Jhon" }.select(p.info)
val infoList: List< PersonInfo > = db.runQuery(query)
上記は一見シンプルで良いが、下記のように一度エンティティで取得してからmap
すれば同じことが実現できる。
val query: Query<List<Person>> = QueryDsl.from(p).where { p.info.name eq "Jhon" }
val people: List<Person> = db.runQuery(query)
val infoList: List<PersonInfo> = people.map { it.info }
Spring Data JDBCのドキュメントにある@Embedded.onEmpty
の機能はKotlinのnullabilityで表現できそう。
Spring Data JDBCのドキュメント:
class MyEntity {
@Id
Integer id;
@Embedded(onEmpty = USE_NULL)
EmbeddedEntity embeddedEntity;
}
Komapperで表現するとしたら:
@KomapperEntity
data class MyEntity(
@Id
val id: Int,
@KomapperEmbedded
val embeddedEntity: EmbeddedEntity?
)
Embedded Valueが複数のエンティティクラスから参照されることを考えると、JPAのAttributeOverride
やAttributeOverrides
相当の機能が必要になる。
同じ型のEmbedded Valueが1つのEntityに複数存在する場合を考慮しないといけない
@KomapperEntity
data class Person(
@KomapperEmbeddedId
val id: PersonId,
@KomapperEmbedded
val info1: PersonInfo,
@KomapperEmbedded
@KomapperAttributeOverride(...)
val info2: PersonInfo
)
実装してKomapper v1.3.0としてリリースしました。