Lazy Initialization Errors from Refreshes
How can I prevent LazyInitializationExceptions from being thrown when a page is requested multiple times? If I simply hold Ctrl-R on a page in my webapp, I consistently receive this message in my log files.
I have the following interceptor configured in my servlet.xml file:
<mvc:interceptors>
<bean
class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor" />
</mvc:interceptors>
Yet I constantly receive the following errors:
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)
Note: Turning logging on the Interceptor I clearly see that it's being invoked and opening / closing transactions:
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
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 - Narrowing proxy to class core.model.entities.Subclass - this operation breaks == 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 - Narrowing proxy to class core.model.entities.Subclass - this operation breaks == 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 - Flushing single Hibernate Session in OpenSessionInViewInterceptor 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 - Rendering view [eqip.core.springmvc.extensions.velocity.VelocityToolsLayoutView: name 'pages/myEqip'; URL [pages/main.xhtml]] in DispatcherServlet with name '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 - Rendering screen content template [pages/main.xhtml] 2011-09-23 15:36:54,开发者_JAVA技巧384 [http-8080-5] DEBUG org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor IP134.167.141.34 CV#ef955014-cc9d-42fc P#75004 - Closing single Hibernate Session in OpenSessionInViewInterceptor
Using Spring 3.0.5, Hibernate 3.6.5, velocity 1.7
Final Fix: Was adding the following to our controller declarations:
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
This allowed us to keep use of our interceptors and ensure that we were getting new copies of our pre-loaded pieces on each request.
It might be that you are saving some hibernate objects in the session, these objects might have uninitialized proxies.
Each time you press Ctrl+R, new request opens, and it is not possible to initialize proxy object from previous request durring the current request and as the result LazyInitializationException
exception raises.
If this is not your case, then try to dig it in this direction.
Are you sure that interceptor class is actually called? Get the sources, and do a debug on it to see if the execution actually gets to it. Make sure you've actually declared that interceptor as an interceptor in your spring mvc configuration:
<bean id="urlMapping"class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="openSessionInViewInterceptor"/>
</list>
</property>
<property name="mappings">
</bean>
Or you can just go with the simpler OpenSessionInVIewFilter, which only needs to be configured as a servlet filter that intercepts /* (or a generic enoug URL to encompass all the urls of your controllers that deal with hibernate entities).
Write a Class like :-
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);
}
}
Declare it in web.xml like this:-
<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>
精彩评论