2008/03/07からのアクセス回数 23037 HibernateのLazy initializeエラーでビューを表示できない †Cart問題の最後で、注文者の情報をいれた後に内容を表示するときに以下のようなエラーが発生しました。 こんな最後の最後に勘弁してくださいと気持ちでした! -- 例外のトレース org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: example.cart.domain.Order.lineItemList, no session or session was closed org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:488) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:431) javax.servlet.http.HttpServlet.service(HttpServlet.java:689) javax.servlet.http.HttpServlet.service(HttpServlet.java:802) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:75) -- 本来の原因 org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: example.cart.domain.Order.lineItemList, no session or session was closed org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358) --途中省略 org.apache.velocity.Template.merge(Template.java:254) --途中省略 org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1158) --途中省略 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:431) javax.servlet.http.HttpServlet.service(HttpServlet.java:689) javax.servlet.http.HttpServlet.service(HttpServlet.java:802) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:75) どうやらビューでコレクションの要素であるLineItemを遅延初期化(lazily initialize)しようとした時に、 Hinbernateのsessionがクローズしていたので例外が発生みたいです。 そこで、ネット"Spring Hibernate Lazy initialize error" をキーに検索すると に同様のケースが報告されていました。 解決策としては、Hibernateマッピングファイルのlazy属性をfalseにするというものでした。 そこで、以下のようにOrderのbagタグにlazy="false"を入れ <bag name="lineItemList" cascade="all" table="T_LINEITEM" lazy="false"> <key column="orderId" foreign-key="ID"/> <one-to-many class="example.cart.domain.LineItem"/> </bag> LineItemのmany-to-oneタグにも同様に <many-to-one name="product" column="productId" cascade="save-update" lazy="false" class="example.cart.domain.Product"/> としたら、正常に動作するようになりました。 Hibernateがデフォルトでlazy initializeをtrueにしている理由 †では、どうしてHibernateがデフォルトでlazy initializeをtrueにしているのでしょう。 それは、パフォーマンスを向上するため不要な初期化をさけるためにlazy initializeをtrueにしているのだと思われます。 とするとlazy="false"の設定は、本当の対処方法ではないのではないかと考え、どこかに情報がないか調べました。 今度は、"org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: "で検索すると Originally Posted by karldmoore If the association is lazy loaded and the Session has been closed then this won't work. You either need to eagerly load the association, use something like OpenSessionInView to extend the Session around the request or reattach the entity to the Session before trying to lazy load. という回答を見つけました。 どうやら、OpenSessionInViewを使えば、クローズしていたsessionでlazy loadができるみたいです。 にOpenSessionInViewの使い方が出ていました。 また、Spring LIVEの240ページにも同様の説明がでていました。 私の解決策 †OpenSessionInViewには、批判的なコメントも見受けられました。 それは、
上記の問題を考え合わせた結果、
filterのinit-paramでsingleSessionとflushModeを指定すると方法がベストだと思います。 コメント †この記事は、 皆様のご意見、ご希望をお待ちしております。 Tweet |