轉載http://tuoxie007.javaeye.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(){}
-
- }
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>
<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>
<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>