2012-09-10 28 views
2

我正在使用Spring Roo和Vaadin来创建(简单)数据库应用程序。有一个视图显示一个包含实体的表。对于要显示的表,Hibernate需要延迟加载1:n引用的实体。这适用于小型表格,但只要表格变大,只有第一部分显示正确,并且会发生以下异常。LazyInitializationException(Spring和Vaadin)尽管OpenEntityManagerInView

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过滤器正在被调用。

任何想法?非常感谢!

+0

听起来不像这样适用于这种情况,但您也可以ge如果对象未连接到_current_会话,则返回LazyInitializationException ... –

回答

6

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

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

一些解决方案:

  • 使用你反对的渴望JPA获取(@ManyToOne (fetch= FetchType.EAGER)
  • 负载连接抓取查询(例如SELECT mag FROM Magazine mag LEFT JOIN FETCH mag.articles WHERE mag.id = 1See more
  • 将EclipseLink(的EclipseLink将打开一个新的会话负载分离对象的延迟加载字段)[我们正在使用这种方法]
+0

非常感谢您的回答。事实上,你的解释是非常合理的。有没有可能使用Hibernate,仍然使用延迟加载? (像重新关联实体到新打开的会话?)也许我应该尝试EclipseLink(但目前,应用程序使用Hibernate,所以我期望一些切换工作)。 –

+1

@MatthiasWuttke您可以尝试使用[hbncontainer](http://vaadin.com/directory#addon/hbncontainer)。它需要一个Hibernate会话,但你可以用Spring注入一个[See Docs](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/orm.html#orm-休眠直)。 – TRex

+1

你可以看看这个[博客文章](http://blog.9mmedia.com/?p=272) – TRex

相关问题