在hibernate中,由于hibernate有懒加载的问题,当没有调用到指定对象的值时,sql语句并未发出,这时当结果 返回到页面,页面从对象中取值。而此时连接已经关闭,也取不到对象的值,所以这时可以使用filter来解决这一问题.
当然了,filter也有配置的顺序问题.这个filter必须配置在最外层,也就是struts的filter的外围才能正常工作,所以
请看如下代码.
package com.fdy.oa.web;
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.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.fdy.oa.utils.HibernateUtils;
public class SessionFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
try {
Class.forName("com.fdy.oa.utils.HibernateUtils");// 类加载时就加载了配置文件.
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
Session session = null;
try {
session = HibernateUtils.getSession();// 取到当前线程的session.
Transaction tx = session.beginTransaction();
chain.doFilter(req, res);
tx.commit();
} catch (HibernateException e) {
session.beginTransaction().rollback();
e.printStackTrace();
} finally {
HibernateUtils.close();// 多线程条件下,如果不把session放入threadlocal中,你所操作的session可能不是之前的session.
}
}
}
在这段代码中,session在filter中进行关闭,这样就保证jsp页面能取到对应的值.
再来看其中调用的hibernateutils的代码,可以看出来,session是被放在了threadlocal中,threadlocal保证每一个线程有一个副本,而不用考虑同步的问题.这也很好的解决了session的值不互相干扰的问题.
package com.fdy.oa.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
private static Configuration cfg;
private static SessionFactory factory;
private static ThreadLocal<Session> local;
static {
cfg = new Configuration().configure("hibernate_mysql.cfg.xml");
factory = cfg.buildSessionFactory();
local = new ThreadLocal<Session>();
}
public static Session getSession() {
if (local.get() == null) {
local.set(factory.openSession());
}
return local.get();
}
public static void close() {
if (local.get() != null && local.get().isOpen()) {
local.get().close();
local.set(null);
}
}
}
现在请各位自己动手尝试一下!感受一下自建sessionfilter而不是用spring的OpenSessionInView的方法.