2012-09-10 29 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

相關問題