ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException
{
Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}
在代码中,只要借助上面这个工具类获取Session 实例,我们就可以实现线程范围内的
Session 共享,从而避免了在线程中频繁的创建和销毁Session 实例。不过注意在线程结束
时关闭Session。
同时值得一提的是,新版本的Hibernate在处理Session的时候已经内置了延迟加载机
制,只有在真正发生数据库操作的时候,才会从数据库连接池获取数据库连接,我们不必过于担
心Session的共享会导致整个线程生命周期内数据库连接被持续占用。
对于Web程序
而言,我们可以借助Servlet2.3规范中新引入的Filter机制,轻松实现线程生命周期内的
Session管理(关于Filter的具体描述,请参考Servlet2.3规范)。
Filter的生命周期贯穿了其所覆盖的Servlet(JSP也可以看作是一种特殊的Servlet)
及其底层对象。Filter在Servlet被调用之前执行,在Servlet调用结束之后结束。因此,
在Filter 中管理Session 对于Web 程序而言就显得水到渠成。下面是一个通过Filter 进
行Session管理的典型案例:
public class PersistenceFilter implements Filter
{
protected static ThreadLocal hibernateHolder = new ThreadLocal();
public void doFilter(ServletRequest request, ServletResponse
response, FilterChain chain)
throws IOException, ServletException
{
hibernateHolder.set(getSession());
try
{
......
chain.doFilter(request, response);
......
}
finally
{
Session sess = (Session)hibernateHolder.get();
if (sess != null)
{
hibernateHolder.set(null);
try
{
sess.close();
}
catch (HibernateException ex) {
throw new ServletException(ex);
}
}
}
}
......
Hibernate Developer's Guide Version 1.0
September 2, 2004 So many open source projects. Why not Open your Documents?
}
通过在doFilter中获取和关闭Session,并在周期内运行的所有对象(Filter链中其
余的Filter,及其覆盖的Servlet 和其他对象)对此Session 实例进行重用,保证了一个
Http Request处理过程中只占用一个Session,提高了整体性能表现。
在实际设计中,Session的重用做到线程级别一般已经足够,企图通过HttpSession实
现用户级的Session重用反而可能导致其他的问题。凡事不能过火,Session重用也一样。