JPA(Hibernate)におけるEnumの扱いって難しい
※だいたいJPA2.0とHibernate3.6.Xぐらいの話
OrdinalかStringか
EnumをDBに保存する方法としては2種類ある。
序数として保存するか、文字列として保存するか。
序数の場合はEnum#ordinalで保存されて、文字列の場合はEnum#nameで保存されるらしい。
直感とズレはなさそう。
ただし、使ってみると一長一短だったりする。
Ordinalの場合
良い点
- DBに保存されるのは序数(数値)のため、容量的に優しい
- ソート(order by)がしやすい
悪い点
- Enumクラスの途中に新しい要素が追加された場合にすでにDBに入っている値がずれる。(序数がずれるため)
- 保守時の可読性が低い
Stringの場合
良い点
- DBを直接見たときに判りやすい
- Enumクラスの途中に追加された場合でも値がずれない。
悪い点
- 容量にやさしくない
- ソートがしにくい(文字列でのソートになるはず)
見事に一長一短。
悪いところの回避策はある程度簡単に思いつきはするものの
どうしているところが多いんでしょうねぇ。
私はあとで判りやすいStringを推したい。
適当に調べてみるとEntityから出し入れするときだけEnumを使用してDB保存時はIntegerを使うという例を見つけたけれども、
やはりEnumを直接保存するのは現時点では微妙ということかなぁ。
仕様としてEnumを文字列保存かつソートができるように+αで何かというのを用意してくれているといいと思うのですが。
EnumといえばEnumSet
私はよく使うのだけれども、どう保存するのが良いのでしょう?
保存するときの考え方はとりあえず3通り思いつきます。
- DBに保存するときにEnum一つづつカラムを作成して、1レコードとして保存する。(Enumが増えればカラム数がどんどん増える)
- 通常のCollectionと同様にEnumの数だけレコードを作成する。(OneToMenyでレコード数がどんどん増える)
- bitフィールドか何かに変換してひとつのカラムに無理やり突っ込む(どう考えても保守性が低い)
テーブルが増えすぎるのも困りものなので、あまりEnumの要素数が変動しないことが前提であれば1がいい気がするのだけれども、もっといい方法があるのかなぁ。