関連(@OneToManyなど)では、FetchType.EAGERを前提に設計していたところが多いのですが、「そんなに同時にEAGERフェッチはできませんよ」というエラーがおきてしまった。※これがHibernateの仕様なのか、JPAの仕様なのか、イマイチ分かりません。
こういう関連がPersistenceUnit内に一つでもあると、EntityManagerFactoryを生成した時点でアウトです。
とりあえずデフォルト(FetchType.LAZY)に戻すと解消します。
EAGERが使えないのなら、プロパティにアクセスしまくって、強制的にLAZYフェッチしてしまえばいいので、このエラーはあまりたいした問題ではなさそう。大問題は、次です。
今までの自分の考え方に、大きな間違いがあることに気づきました。Entity Managerから抜け出したEntityは、POJOではなく、Detached Entity(分離されたエンティティ)という中途半端な状態になり、自由にはアクセスできなくなるようです。
例えば、こんな感じです。UserRoleとUserが @OneToMany の場合
私は、@Entityが宣言されたPOJOは、JSFからみればDTO(POJO)、EntityManagerからみればEntityである。と思い込んでいました。なので、今作ってるシステムでは、JSFからEntityのプロパティを直接触って永続化する方法を取っています。
しかし、どのコンテキストから見てもあくまでもEntityだ、ということになると、JSFから触るのは確かにイヤです。Open Session In Viewなんてのも、疎結合もクソもなくなるし。
あれー、どうすればいいんだろー?と思ったら、とっくの昔に先人達のすばらしいエントリがありました。さすがは、はてな。
koichikのひとりごと
矢野勉のはてな日記
どちらの意見も、うんうん、そうだそうだ、と。結局は、koichikさんの結論のように、DTOで層分離しなければならないんでしょう。
それはわかるんですが、でも、もっとラクしたい。だって、POJOなんでしょ?
そもそもDetachedの仕様はヘン。というかおせっかいがすぎます。
POJOはPOJOにしてくれ、頼むから。
たぶん、EntityとDBの整合が取れなくなることを防いで、壊れる原因になるメソッドには触れないようにしてるのでしょうが・・
壊したりしないから、触らせてほしい。
それに、Detachedの状態でLAZYフェッチしたときは、nullが返ればそれで十分です。それで困る人って、いる?Exception吐く方が困るんですけど。
そのくらいは開発側が責任とります。
こんなヘンな縛りがなければ、どれほどラクになるだろうか。Javaのハタ迷惑なクソまじめっぷりを感じて、ちょっとイライラしています。
・・・さてそうは言っても、仕様だからショウガナイとして、これからどうしよう。DTOを挟むか、このまま突っ走るか。・・・
問題になるのは関連操作だけだから、現状のままで、行けるところまで行こうかな。それで7割がうまくいくなら御の字か。