DB値 -> EntityとEntity -> DBで値を変換する為の例のあれです。
よく例として上げられる(上げやすい)のがintとboolの変換とかですね。
Entityとしてはboolで扱っておいて、DB上はintで1/0で保存する、みたいな。
このConverter自体は深く掘り下げたりはしませんが、正直、なんかうまく動かないことが多いイメージが強いです。
まあ、Entityのインスタンス生成前に挟まれるであろう処理なので、利用しているデータストアの種類やHibernate等のアクセサに深く依存してそう、というか特定ケースでのHibernateでは動作しないようなissueも上がってたような気がします。
そんなこんなで、あまり信用していないのと、ちょっとレイヤーが変わるかもだけれどEntityのfieldにdelegate貼ったら代用できるよね、と思い、試してみました。
Converterをdelegateで代用してみる
Entityを用意
@Entity @Table class Memo { @Column("title") var title = "" @Column var value = "" }
特に特筆する点はないかと。
Interfaceを用意してEntityに貼る
interface TitleHaving { var _title: String } class Memo: TitleHaving { @Column("title") override var _title = ""
タイトルを持ってるよー、のインターフェースです。
Entityへはtitleを_titleへ変更して実装。
delegateを用意
class TitleQuestionConverter: ReadWriteProperty<TitleHaving, String> { override fun setValue(thisRef: TitleHaving, property: KProperty<*>, value: String) { thisRef._title = value } override fun getValue(thisRef: TitleHaving, property: KProperty<*>): String = "${thisRef._title}?" }
タイトル文言を疑問文にしてしまうというどうでもいいdelegateにしました。
Entityへ入れる
class Memo: TitleHaving { @Column("title") override var _title = "" @Column var value = "" @delegate:Transient var title by TitleQuestionConverter() }
delegateするfield名をtitleとして、あたかも利用する側には@Columnがついてるfieldのように見せかけます。
その実は_titleの値を変換して取得、設定された場合にはそのまま_titleへ格納、@Columnが指定されている_title側はsaveでそのまま保存され、
対する自身は@delegate:Transientで、delegate先に@Transientを指定することで永続化対象ではなくします。
getValueで対象fieldへアクセスされてしまうので、LAZYが指定されたアソシエーション列等の場合はLAZYの意味が無くなったりしますが、簡単な変換なら十分作用すると思います。
いじょ