关于Hibernate懒加载问题的最终解决方案

本文介绍了解决Hibernate懒加载导致的LazyInitializationException问题的方法。通过在JSP渲染前后控制Session的开启与关闭,避免异常的发生。提供了自定义过滤器和使用Spring提供的OpenSessionInViewFilter两种解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值