2011-09-23 50 views
3

如何防止在多次請求頁面時引發LazyInitializationException?如果我只是在我的web應用程序的一個頁面上按住Ctrl-R,我始終會在我的日誌文件中收到此消息。來自刷新的延遲初始化錯誤

我在servlet.xml文件配置了以下攔截器:

<mvc:interceptors> 
    <bean 
    class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor" /> 
</mvc:interceptors> 

然而,我不斷收到以下錯誤:

2011-09-23 15:14:28,854 [http-8080-23] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/web-app].[springmvc] - Servlet.service() for servlet springmvc threw exception 
org.hibernate.LazyInitializationException: illegal access to loading collection 
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:366) 
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111) 
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186) 

注:在攔截記錄打開我清楚地看到,它被調用並打開/關閉交易:

2011-09-23 15:36:53,229 [http-8080-5] DEBUG org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor IP134.167.141.34 CV#ef955014-cc9d-42fc P#75004 - Opening single Hibernate Session in OpenSessionInViewInterceptor 
2011-09-23 15:36:53,229 [http-8080-5] WARN eqip.core.springmvc.extensions.interceptors.AbstractAgencyDataInterceptor IP134.167.141.34 CV#ef955014-cc9d-42fc P#75004 - Pre handle: http://134.167.141.34:8080/web-app/main.xhtml Status: 200 

2 011-09-23 15:36:53,511 [http-8080-5] WARN org.hibernate.engine.StatefulPersistenceContext.ProxyWarnLog IP134.167.141.34 CV#ef955014-cc9d-42fc P#75004 - 將代理縮小到class core.model .entities.Subclass - 此操作中斷== 2011-09-23 15:36:53,511 [http-8080-5] WARN org.hibernate.engine.StatefulPersistenceContext.ProxyWarnLog IP134.167.141.34 CV#ef955014-cc9d-42fc P#75004 - 縮小代理類到core.model.entities.Subclass - 此操作中斷== 2011-09-23 15:36:53,916 [http-8080-5] DEBUG org.springframework.orm.hibernate3.support。 OpenSessionInViewInterceptor IP134.167.141.34 CV#ef955014-cc9d-42fc P#75004 - 在OpenSessionInViewInterceptor中刷新單個Hibernate會話2011-09-23 15:36:53,916 [http-8080-5] DEBUG org.springframework.web.servlet。 DispatcherServlet IP134.167.141.34 CV#ef955014-cc9d-42fc P#75004 - 渲染視圖[eqip.core.springmvc.extensions.velocity.Velocit yToolsLayoutView:name'pages/myEqip'; DispatcherServlet中的URL [pages/main.xhtml]],名稱爲'springmvc' 2011-09-23 15:36:54,213 [http-8080-5] DEBUG eqip.core.springmvc.extensions.velocity.VelocityToolsLayoutView IP134.167.141。 34 CV#ef955014-cc9d-42fc P#75004 - 渲染屏幕內容模板[pages/main.xhtml] 2011-09-23 15:36:54,384 [http-8080-5] DEBUG org.springframework.orm.hibernate3。 support.OpenSessionInViewInterceptor IP134.167.141.34 CV#ef955014-cc9d-42fc P#75004 - 中的OpenSessionInViewInterceptor

關閉單個的Hibernate Session使用Spring 3.0.5,3.6.5休眠,速度1.7

最終修復 :將以下內容添加到我們的控制器聲明中:

@Scope(BeanDefinition.SCOPE_PROTOTYPE) 

這使我們能夠繼續使用我們的攔截器,並確保我們在每個請求中獲得了預先加載的部分的新副本。

回答

0

這可能是因爲你在會話中保存了一些hibernate對象,這些對象可能有未初始化的代理。

每次按Ctrl + R時,都會打開新的請求,並且在當前請求期間不可能從先前請求初始化代理對象,並且結果LazyInitializationException異常引發。

如果這不是你的情況,那麼試着在這個方向挖掘它。

+0

哪個會話? Http會話或Hibernate會話?我將如何驗證? – Scott

+0

Http會話,不知何故,您的單元化代理被轉發到下一個請求。我只是建議你看看你的應用程序邏輯或者只是調試它。 –

+0

我仔細檢查了一下。也許有些東西堅持重定向。 – Scott

0

您確定實際調用了攔截器類嗎?獲取源代碼,並對其進行調試以查看執行是否真正達到它。請確保你實際上已經宣佈攔截在您的Spring MVC配置的攔截器:

<bean id="urlMapping"class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 
<property name="interceptors"> 
<list> 
<ref bean="openSessionInViewInterceptor"/> 
</list> 
</property> 

<property name="mappings"> 

</bean> 

或者,你可以用簡單的OpenSessionInViewFilter,只需要配置一個Servlet過濾器進入其截取/ *(或者一個通用的enoug URL來包含處理hibernate實體的控制器的所有url)。

+0

我們收到與OSIVF同樣的問題也是如此。 – Scott

+0

相信我,我感覺到你。這是使用Hibernate的「祝福」之一,它是如此糟糕,被包裹在另一個像Spring這樣的重量級框架中,你就會迷失在事情中。我選擇避免LAzyInitialisation ...是從一開始就使用「獲取連接」來爲當前視圖獲取所有需要的數據。我的意思是,爲什麼你需要讓一個足夠的Hibernate發出一堆選擇? –

0

寫一個類,如: -

public class CustomHibernateSessionViewFilter extends OpenSessionInViewFilter { 

protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException { 
    Session session = super.getSession(sessionFactory); 
    session.setFlushMode(FlushMode.COMMIT); 
    return session; 
} 

protected void closeSession(Session session, SessionFactory factory) { 
    session.flush(); 
    super.closeSession(session, factory); 
} 

}

聲明它在這樣的web.xml: -

<filter> 
    <filter-name>OSIVF Filter</filter-name> 
    <filter-class>your.path.to.CustomHibernateSessionViewFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>OSIVF Filter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping>