【问题标题】:LazyInitializationException (Spring and Vaadin) despite of OpenEntityManagerInView尽管有 OpenEntityManagerInView,但 LazyInitializationException(Spring 和 Vaadin)
【发布时间】:2012-09-03 00:22:32
【问题描述】:

我将 Spring Roo 和 Vaadin 用于(简单)数据库应用程序。有一个视图显示包含实体的表。对于要显示的表格,Hibernate 需要延迟加载 1:n 引用的实体。这适用于小表格,但一旦表格变大,只有第一部分正确显示,并出现以下异常。

com.vaadin.data.util.MethodProperty$MethodException
    at com.vaadin.data.util.MethodProperty.getValue(MethodProperty.java:612)
    at com.vaadin.data.util.AbstractProperty.toString(AbstractProperty.java:78)
    at com.vaadin.ui.Table.formatPropertyValue(Table.java:3476)
    at eu.wuttke.tinyscrum.ui.dashboard.DashboardTaskStoryTable.formatPropertyValue(DashboardTaskStoryTable.java:66)
    at com.vaadin.ui.Table.getPropertyValue(Table.java:3428)
    at com.vaadin.ui.Table.getVisibleCellsNoCache(Table.java:1853)
    at com.vaadin.ui.Table.refreshRenderedCells(Table.java:1477)
    at com.vaadin.ui.Table.enableContentRefreshing(Table.java:2645)
    at com.vaadin.ui.Table.changeVariables(Table.java:2491)
    at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.changeVariables(AbstractCommunicationManager.java:1455)
    at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1399)
    at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1318)
    at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:763)
    at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:296)
    at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:501)
    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.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:147)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    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:127)
    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:298)
    at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
    at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
    at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:769)
    at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:698)
    at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:891)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
    at java.lang.Thread.run(Thread.java:679)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.GeneratedMethodAccessor841.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.vaadin.data.util.MethodProperty.getValue(MethodProperty.java:610)
    ... 34 more
Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
    at eu.wuttke.tinyscrum.domain.Iteration_$$_javassist_1.getName(Iteration_$$_javassist_1.java)
    at eu.wuttke.tinyscrum.domain.Iteration_Roo_JavaBean.ajc$interMethodDispatch1$eu_wuttke_tinyscrum_domain_Iteration_Roo_JavaBean$eu_wuttke_tinyscrum_domain_Iteration$getName(Iteration_Roo_JavaBean.aj)
    at eu.wuttke.tinyscrum.domain.TaskAndStory.getIterationName(TaskAndStory.java:32)
    ... 38 more

我从其他 Hibernate 应用程序中知道这个 LazyInitializationException 异常,它在会话未打开或已经再次关闭时发生。但是查看堆栈跟踪,似乎 OpenEntityManagerInView 过滤器正在被调用。

有什么想法吗?非常感谢!

【问题讨论】:

  • 在这种情况下听起来并不适用,但如果对象未连接到 current 会话,您也可以获得 LazyInitializationException...

标签: java spring hibernate jpa vaadin


【解决方案1】:

Vaadin 在服务器端具有持久状态。如果您将对象绑定到 Vaadin 组件(例如,通过使用 BeanItemContainer),您的对象将在服务器端“存活”多个请求。

另一方面,Spring(通过OpenEntityManagerInView)将为每个请求创建一个新的EntityManager(EntityManagers 不是威胁安全的)并在请求后关闭它。这样,您已经加载的 Entities 将被分离(EM 不再可用),并且当 Vaadin 向例如加载更多表行,延迟加载文件将无法加载(您将获得LazyInitializationException),因为加载它们的 EM 不再存在。

一些解决方案:

  • 使用 Eager JPA Fetch (@ManyToOne (fetch= FetchType.EAGER))
  • 使用 JOIN FETCH 查询加载您的对象(例如 SELECT mag FROM Magazine mag LEFT JOIN FETCH mag.articles WHERE mag.id = 1 See more
  • 使用 EclipseLink(EclipseLink 将打开一个新的 Session 来加载分离对象的延迟加载字段)[我们正在使用这种方法]

【讨论】:

  • 非常感谢您的回答。确实,你的解释很有道理。是否有可能使用 Hibernate,仍然使用延迟加载? (比如将实体重新关联到新打开的会话?)也许我应该尝试一下 EclipseLink(但目前,应用程序使用 Hibernate,所以我希望进行一些切换工作)。
  • @MatthiasWuttke 您可以尝试使用hbncontainer。它需要一个 Hibernate 会话,但您可以使用 Spring See Docs 注入一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-27
  • 2022-12-22
  • 1970-01-01
  • 1970-01-01
  • 2015-10-02
  • 2015-07-31
  • 1970-01-01
相关资源
最近更新 更多