105

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,偶现在也不知道到底是怎么个情况,有高人请指点。

转载地址:http://tuoxie007.iteye.com/blog/334853 

猜你喜欢

转载自poterban.iteye.com/blog/1148064
105
今日推荐