Criteria で Fetchmode.JOIN を使用した時の注意点

hibernate を使っていて、普段は 関連を lazyで扱いたいんだけど、あるポイントではlazyをfalseにして使いたい、ということがよくある。その場合、マッピングファイルのほうでは lazy=true にしておき、呼び出すプログラムのほうで明示的に FetchModeを変えてやるのが一般的。

HQL を使う場合は left join fetch を指定する。Criteriaを使うときは、以下のようにする。

  session.createCriteria("Entity")
     .setFetchMode("関連名", FetchMode.JOIN)
     .add(Expression.・・・

遅延ロードではなく、一度に読み込みたいフィールドの関連名と、フェッチモードを指定する。フェッチモードは、FetchMode.JOIN と FetchMode.SELECT がある。JOINはアウタージョインを使って取得し、SELECTはその都度読み込み、つまり遅延ロード。昔は FetchMode.EAGER と FetchMode.LAZY だったのが、名前が変わったらしい。(昔のは非推奨になっている。)

さて、このように JOIN してリストを取得すると、ちょっと困ったことが起きる。1対多の関係のオブジェクト、AとBがあるとする。Aをメインに、BをJOINしてリストを取得すると、Aが重複してしまうのだ。どういうことかというと、たとえば、Aと対応するB-1、B-2があったとする。このAを先ほどのJOINでBも一緒に取得すると、リストのサイズが2になっている。まぁ、SQLのJOINを忠実に再現してるのかもしれないが、あまりうれしくない機能だなぁ。。。

いろいろ調べてみると、どうやらこれは仕様で、重複したデータを欲しくないなら、帰ってきたListをSetに変換しろ、ということらしい。びみょ〜〜(−−;

マッピングファイルで、lazy=false にした場合はそんなことないのに、なんかとかうまい方法はないものか。。