JPA(Hibernate)におけるEnumの扱いって難しい

※だいたいJPA2.0とHibernate3.6.Xぐらいの話

Enumはよく使うのだけれども

JPA(というかHibernate)で使うと色々と考えどころがある。
とりあえず二つ。

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通り思いつきます。

  1. DBに保存するときにEnum一つづつカラムを作成して、1レコードとして保存する。(Enumが増えればカラム数がどんどん増える)
  2. 通常のCollectionと同様にEnumの数だけレコードを作成する。(OneToMenyでレコード数がどんどん増える)
  3. bitフィールドか何かに変換してひとつのカラムに無理やり突っ込む(どう考えても保守性が低い)

テーブルが増えすぎるのも困りものなので、あまりEnumの要素数が変動しないことが前提であれば1がいい気がするのだけれども、もっといい方法があるのかなぁ。