2008-05-11
Hibernate 延迟加载引发一串问题
Hibernate的延迟加载技术使要在jsp页面访问数据时产生了 no session的错误,
可以在映射文件添加lazy="false" 来关掉,不过这样就使用不到延迟加载技术了,我用的是struts,所以要用Spring提供的 OpenSessionInViewFilter这个过滤器来处理。
添加后产生了另一个问题,就是OpenSessionInViewFilter找不到SessionFactory这个bean,仔细看了自己的项目有两个的IOC容器,一个是在web.xml中定义的org.springframework.web.context.ContextLoaderListener监听器来启动ioc容器,另一个是struts-config.xml中为了让struts与spring进行无缝集成添加的org.springframework.web.struts.ContextLoaderPlugIn来启动IOC容器供Action使用,sessionFactory就定义在第二个容器中,而矛盾的地方是这两个容器都把自己绑定到了servletContext上,不过绑定的名字不一样,通过OpenSessionInViewFilter的源代码得知(体会到通过Spring的源代码能从根本上认识并解决问题)这个过滤器是按第一个的绑定名去找IOC容器的,而我几乎所有的bean都放到第二个容器里(因为Action使用的bean和DAO都放在这),所以找不到sessionFactory。
知道了问题所在,解决的方法有两种,都是要改写spring的类。第一种改写OpenSessionInViewFilter使它到第二个容器中去找,第二种是改写ContextLoaderPlugIn使在绑定到ServletContext的同时,也用第一种的名字绑定一次,我用的是第二种,因为第一种中要用用到第二钟容器中的绑定名是动态的,很难确定,第二种方式就只需要加一行。
我的方法如下:
建一个类继承ContextLoaderPlugIn,然后覆盖方法ininWebApplicationContext
代码如下:
package com.yourcompany.operation.common;
import org.springframework.web.struts.ContextLoaderPlugIn;
import org.springframework.beans.BeansException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class MyContextLoaderPlugIn extends ContextLoaderPlugIn {
protected WebApplicationContext initWebApplicationContext() throws BeansException, IllegalStateException {
getServletContext().log("Initializing WebApplicationContext for Struts ActionServlet '" +
getServletName() + "', module '" + getModulePrefix() + "'");
WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = createWebApplicationContext(parent);
if (logger.isInfoEnabled()) {
logger.info("Using context class '" + wac.getClass().getName() + "' for servlet '" + getServletName() + "'");
}
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
//自己添加的内容,为了让OpenSessionInViewFilter也能找到Spring容器
getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
if (logger.isDebugEnabled()) {
logger.debug("Published WebApplicationContext of Struts ActionServlet '" + getServletName() +
"', module '" + getModulePrefix() + "' as ServletContext attribute with name [" + attrName + "]");
}
return wac;
}
}
可以在映射文件添加lazy="false" 来关掉,不过这样就使用不到延迟加载技术了,我用的是struts,所以要用Spring提供的 OpenSessionInViewFilter这个过滤器来处理。
添加后产生了另一个问题,就是OpenSessionInViewFilter找不到SessionFactory这个bean,仔细看了自己的项目有两个的IOC容器,一个是在web.xml中定义的org.springframework.web.context.ContextLoaderListener监听器来启动ioc容器,另一个是struts-config.xml中为了让struts与spring进行无缝集成添加的org.springframework.web.struts.ContextLoaderPlugIn来启动IOC容器供Action使用,sessionFactory就定义在第二个容器中,而矛盾的地方是这两个容器都把自己绑定到了servletContext上,不过绑定的名字不一样,通过OpenSessionInViewFilter的源代码得知(体会到通过Spring的源代码能从根本上认识并解决问题)这个过滤器是按第一个的绑定名去找IOC容器的,而我几乎所有的bean都放到第二个容器里(因为Action使用的bean和DAO都放在这),所以找不到sessionFactory。
知道了问题所在,解决的方法有两种,都是要改写spring的类。第一种改写OpenSessionInViewFilter使它到第二个容器中去找,第二种是改写ContextLoaderPlugIn使在绑定到ServletContext的同时,也用第一种的名字绑定一次,我用的是第二种,因为第一种中要用用到第二钟容器中的绑定名是动态的,很难确定,第二种方式就只需要加一行。
我的方法如下:
建一个类继承ContextLoaderPlugIn,然后覆盖方法ininWebApplicationContext
代码如下:
package com.yourcompany.operation.common;
import org.springframework.web.struts.ContextLoaderPlugIn;
import org.springframework.beans.BeansException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class MyContextLoaderPlugIn extends ContextLoaderPlugIn {
protected WebApplicationContext initWebApplicationContext() throws BeansException, IllegalStateException {
getServletContext().log("Initializing WebApplicationContext for Struts ActionServlet '" +
getServletName() + "', module '" + getModulePrefix() + "'");
WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = createWebApplicationContext(parent);
if (logger.isInfoEnabled()) {
logger.info("Using context class '" + wac.getClass().getName() + "' for servlet '" + getServletName() + "'");
}
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
//自己添加的内容,为了让OpenSessionInViewFilter也能找到Spring容器
getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
if (logger.isDebugEnabled()) {
logger.debug("Published WebApplicationContext of Struts ActionServlet '" + getServletName() +
"', module '" + getModulePrefix() + "' as ServletContext attribute with name [" + attrName + "]");
}
return wac;
}
}







评论排行榜