关于Hibernate懒加载问题的最终解决方案
看到一篇Hibernate懒加载的文章,所以转载,原地址如下:
http://tuoxie007.iteye.com/blog/334853
Hibernate的强大之处之一是懒加载功能,可以有效的降低数据库访问次数和内存使用量。但用的不好就会出现org.hibernate.LazyInitializationException。
这个异常出现的原因很简单,主要时在加载懒数据时Session已经关闭造成的.
那么OK,我们来考虑怎么解决吧。
我们只要在渲染JSP之前不要关闭Session,而在JSP渲染之后再关闭就OK啊。我们知道,在JSP/Servlet中,可以配置过滤器来实现这种功能。
我们考虑两种情况的解决方案: 单使用Hibernate和用Spring来管理Hibernate。
1. 单使用Hibernate:
我们可以自己写一个过滤器:
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的配置:
<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的配置:
<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,偶现在也不知道到底是怎么个情况,有高人请指点。