Why am I getting a Hibernate LazyInitializationException in this Spring MVC web application when the data displays correctly?

后端 未结 6 405
太阳男子
太阳男子 2020-12-29 11:31

I am attempting to create a web application using Spring MVC, with Hibernate as its ORM layer. However, due to my inexperience with both frameworks I\'m struggling.

相关标签:
6条回答
  • 2020-12-29 11:45

    The Hibernate.initialize(list) call doesn't initialize the target entity objects that are referenced in the collection. You would need to iterate over reports and initialize each individual object. The call to initialize reports turns a proxy collection into a concrete collection of Report proxies. Try code below:

    for(Report r : reports)
       Hibernate.initialize(r);
    

    The blunt axe approach is to turn off lazy loading by adding lazy="false" to your hbm classes. This might make sense if you will always iterate over the entire object every time its retrieved (make the initialization step OBE).

    0 讨论(0)
  • 2020-12-29 11:46

    @PersistenceContext(type=PersistenceContextType.EXTENDED)

    is WORK :)

    0 讨论(0)
  • 2020-12-29 11:48

    I just went through this LazyInitialization marathon.

    The core problem is that you're trying to access an hibernate-managed entity outside of the lifecycle of the Session, i.e. in the web view of Spring MVC. In my case, this was a List<> @OneToMany association, which are lazily loaded by default.

    There are a few different approaches -- Mark mentioned one, where you do a "dummy" iteration over the lazy associations. You can also force eager loading, either via the configuration (class-wide) (in JPA it'd be @Fetch(value = FetchType.EAGER)) or more specifically through the HQL. But this will prove more problematic if your lazy associations are Lists.

    The cleanest solution I found was to use Spring's OpenEntityManagerInViewFilter (there's an OpenSessionInViewFilter for Hibernate) -- a simple servlet filter you drop in to web.xml (ahead of your other servlet filters), and Spring will automatically create a thread-safe, transaction-aware Session per-HTTP-request. No more LazyInitializationException!

    0 讨论(0)
  • 2020-12-29 11:49

    Actually,there are three ways to avoid the Lazy Initialization Exception:

    • Set the lazy property to false in the mapping file.I don’t recommend this approach because it will increment the database load and therefore, it will produce a decrease in performance.

    • Keep the session open. Don't close the session before you have processed the data. If the session is open during the request you could get the associated graph but you need to be sure that the action takes within the same transaction.

    • Eagerly fetch the associations. In the HQL query use the keyword "fetch" to retrieve the association. From my point of view this is the best solution to avoid the lazy initialization problem. In HQL, you just need to add the fetch keyword in the from clause to eagerly fetch an association.

    Here is an example:

    from Doctor doc
    left join fetch doc.patients
    where doc.name like ‘Doctor A%’
    

    I have written a post about this issue, with some code examples and links to the github project:

    http://ignaciosuay.com/how-to-avoid-hibernate-lazy-initialization-exception/

    0 讨论(0)
  • 2020-12-29 11:53

    I am just guessing but from the stack trace it seems that toString is being called on SearchRule. Does SearchRule have any child objects that may not have been loaded? If SearchRule.toString was trying to get the value for an uninitialised child object that could result in the LazyInitializationException.

    0 讨论(0)
  • 2020-12-29 11:58

    Ok I am an idiot. My problem is I glanced over the stack trace but didn't really read it. Here is the full stack traces (or one of them, 3 slightly different versions show up in my logs).

    org.hibernate.LazyInitializationException: could not initialize proxy - no Session
        at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:57)
        at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
        at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150)
        at com.generic.orm.generated.SearchRule$$EnhancerByCGLIB$$de674d10.toString(<generated>)
        at java.lang.String.valueOf(String.java:2827)
        at java.lang.StringBuffer.append(StringBuffer.java:219)
        at org.apache.commons.lang.builder.ToStringStyle.appendDetail(ToStringStyle.java:578)
        at org.apache.commons.lang.builder.ToStringStyle.appendInternal(ToStringStyle.java:542)
        at org.apache.commons.lang.builder.ToStringStyle.append(ToStringStyle.java:428)
        at org.apache.commons.lang.builder.ToStringBuilder.append(ToStringBuilder.java:840)
        at org.apache.commons.lang.builder.ReflectionToStringBuilder.appendFieldsIn(ReflectionToStringBuilder.java:606)
        at org.apache.commons.lang.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:759)
        at org.apache.commons.lang.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:287)
        at org.apache.commons.lang.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:121)
        at com.generic.orm.generated.Report.toString(Report.java:141)
        at java.lang.String.valueOf(String.java:2827)
        at java.lang.StringBuilder.append(StringBuilder.java:115)
        at java.util.AbstractCollection.toString(AbstractCollection.java:422)
        at java.lang.String.valueOf(String.java:2827)
        at java.lang.StringBuilder.append(StringBuilder.java:115)
        at java.util.AbstractMap.toString(AbstractMap.java:490)
        at org.netbeans.modules.web.monitor.server.MonitorFilter.recordRequestAttributes(MonitorFilter.java:1376)
        at org.netbeans.modules.web.monitor.server.MonitorFilter.recordRequestData(MonitorFilter.java:1184)
        at org.netbeans.modules.web.monitor.server.MonitorFilter.getDataBefore(MonitorFilter.java:803)
        at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:361)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
        at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
        at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:167)
        at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:239)
        at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1158)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:808)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:431)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
        at java.lang.Thread.run(Thread.java:619)
    

    Netbeans is apparently doing some kind of server side monitoring, which calls the toString, which freaks out because something called by the toString isn't initialized properly. So my problem is two fold, the reflection based ToString seems like a bad idea for hibernate pojos and Netbeans is changing my runtime behavior by trying to observe it.

    Thanks everyone for helping, I think I had just been looking at this problem too closely for too long and needed to step back for a little.

    0 讨论(0)
提交回复
热议问题