关于Hibernate懒加载问题的最终解决方案
2014-07-05 08:38
260 查看
Hibernate的强大之处之一是懒加载功能,可以有效的降低数据库访问次数和内存使用量。但用的不好就会出现org.hibernate.LazyInitializationException。
这个异常出现的原因很简单,主要时在加载懒数据时Session已经关闭造成的,如下图:
![](http://tuoxie007.iteye.com/upload/attachment/76497/325e09ae-0862-3c01-9efb-e8cc442c71cb.jpg)
那么OK,我们来考虑怎么解决吧。
我们只要在渲染JSP之前不要关闭Session,而在JSP渲染之后再关闭就OK啊。我们知道,在JSP/Servlet中,可以配置过滤器来实现这种功能。
![](http://tuoxie007.iteye.com/upload/attachment/76505/92be89e1-f321-32a7-b6dd-cedc16b7471d.jpg)
我们考虑两种情况的解决方案: 单使用Hibernate和用Spring来管理Hibernate。
1. 单使用Hibernate:
我们可以自己写一个过滤器:
Java代码
![](http://tuoxie007.iteye.com/images/icon_star.png)
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;
import org.sunxin.struts2.util.hibernate.HibernateUtil;
public class HibernateThreadFilter implements Filter
{
private SessionFactory sf=null;
public void init(FilterConfig arg0) throws ServletException
{
sf=HibernateUtil.getSessionFactory();
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
try
{
sf.getCurrentSession().beginTransaction();
chain.doFilter(request, response);
sf.getCurrentSession().getTransaction().commit();
}
catch (StaleObjectStateException staleEx)
{
throw staleEx;
}
catch (Throwable ex)
{
ex.printStackTrace();
try
{
//如果发生异常,让事务回滚。
if (sf.getCurrentSession().getTransaction().isActive())
{
sf.getCurrentSession().getTransaction().rollback();
}
}
catch (Throwable rbEx)
{
System.err.println(rbEx.toString());
}
}
}
public void destroy(){}
}
在web.xml中加入这个Filter的配置:
Xml代码
![](http://tuoxie007.iteye.com/images/icon_star.png)
<filter>
<filter-name>HibernateThreadFilter</filter-name>
<filter-class>org.sunxin.struts2.filter.HibernateThreadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HibernateThreadFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这样就在访问后台代码之前打开session,访问后台代码之后关闭session。
2. 用Spring管理Hibernate:
I . Spring为我们提供了这样一个过滤器,我们这样配置一下就OK。
在web.xml中加入Filter的配置:
Xml代码
![](http://tuoxie007.iteye.com/images/icon_star.png)
<filter>
<description>处理Hibernate的懒加载问题</description>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<description>
默认情况下,这个Filter会在Spring的bean池中找一个叫做sessionFactory的bean。如果使用了其他名字的SessionFactory,则应该在这里
指定这个名字。
</description>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
<init-param>
<description></description>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
II . 同时Spring还为我们提供了另一种方案,就是使用拦截器,但偶还不太知道怎么配的,配的没有成功。还有这里需要用到spring-mvc.jar,不在spring.jar里面。还听说这个使用这个拦截器会有一些bug,偶现在也不知道到底是怎么个情况,有高人请指点。
这个异常出现的原因很简单,主要时在加载懒数据时Session已经关闭造成的,如下图:
![](http://tuoxie007.iteye.com/upload/attachment/76497/325e09ae-0862-3c01-9efb-e8cc442c71cb.jpg)
那么OK,我们来考虑怎么解决吧。
我们只要在渲染JSP之前不要关闭Session,而在JSP渲染之后再关闭就OK啊。我们知道,在JSP/Servlet中,可以配置过滤器来实现这种功能。
![](http://tuoxie007.iteye.com/upload/attachment/76505/92be89e1-f321-32a7-b6dd-cedc16b7471d.jpg)
我们考虑两种情况的解决方案: 单使用Hibernate和用Spring来管理Hibernate。
1. 单使用Hibernate:
我们可以自己写一个过滤器:
Java代码
![](http://tuoxie007.iteye.com/images/icon_star.png)
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;
import org.sunxin.struts2.util.hibernate.HibernateUtil;
public class HibernateThreadFilter implements Filter
{
private SessionFactory sf=null;
public void init(FilterConfig arg0) throws ServletException
{
sf=HibernateUtil.getSessionFactory();
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
try
{
sf.getCurrentSession().beginTransaction();
chain.doFilter(request, response);
sf.getCurrentSession().getTransaction().commit();
}
catch (StaleObjectStateException staleEx)
{
throw staleEx;
}
catch (Throwable ex)
{
ex.printStackTrace();
try
{
//如果发生异常,让事务回滚。
if (sf.getCurrentSession().getTransaction().isActive())
{
sf.getCurrentSession().getTransaction().rollback();
}
}
catch (Throwable rbEx)
{
System.err.println(rbEx.toString());
}
}
}
public void destroy(){}
}
在web.xml中加入这个Filter的配置:
Xml代码
![](http://tuoxie007.iteye.com/images/icon_star.png)
<filter>
<filter-name>HibernateThreadFilter</filter-name>
<filter-class>org.sunxin.struts2.filter.HibernateThreadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HibernateThreadFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这样就在访问后台代码之前打开session,访问后台代码之后关闭session。
2. 用Spring管理Hibernate:
I . Spring为我们提供了这样一个过滤器,我们这样配置一下就OK。
在web.xml中加入Filter的配置:
Xml代码
![](http://tuoxie007.iteye.com/images/icon_star.png)
<filter>
<description>处理Hibernate的懒加载问题</description>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<description>
默认情况下,这个Filter会在Spring的bean池中找一个叫做sessionFactory的bean。如果使用了其他名字的SessionFactory,则应该在这里
指定这个名字。
</description>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
<init-param>
<description></description>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
II . 同时Spring还为我们提供了另一种方案,就是使用拦截器,但偶还不太知道怎么配的,配的没有成功。还有这里需要用到spring-mvc.jar,不在spring.jar里面。还听说这个使用这个拦截器会有一些bug,偶现在也不知道到底是怎么个情况,有高人请指点。
相关文章推荐
- 关于Hibernate懒加载问题的最终解决方案
- 关于s2sh框架关于hibernate懒加载问题的说明和解决方案
- 关于C#中hibernate.cfg.xml动态加载问题
- 关于Hibernate3,mysql5 数据库连接超过8小时 连接超时的问题及解决方案(部分摘自网络)
- 关于VS2013无法加载解决方案中项目问题
- Hibernate懒加载常见问题及解决方案
- 关于Hibernate连接SQLServer2005的诸多问题及解决方案
- Weblogic环境下hibernate、antlr类加载冲突问题分析及解决方案
- 关于ThinkPHP遇到无法加载模块 Public问题的解决方案
- 关于hibernate中取消懒加载问题
- 关于Hibernate延迟加载的问题
- 关于VS2010 rcxdti.dll is unable to load rcxdtiui.dll加载失败问题的解决方案
- 关于使用Iscroll.js异步加载数据后不能滑动到最底端的问题解决方案
- 主题:关于hibernate延迟加载的错误解决方案
- Hibernate延迟加载问题及解决方案
- 关于jquery+ajax+json+ssh框架整合,数值异步的问题(暂时解决方案--延迟加载(lazy)改为急加载)
- 关于spring整合hibernate 懒加载异常解决方案
- 关于hibernate急迫加载问题(多重外键关联)
- 关于VS2013连接Oracle数据库提示:“尝试加载oracle客户端时引发badimage,如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题”的解决方案。
- 今天总结:关于hibernate事务乐观锁和elipse启动tomcat报内存不足的最终解决方案