利用ThreadLocal模式管理Session
为什么要用ThreadLocal模式呢?
在利用Hibernate开发DAO模块时,我们和Session打的交道最多,
所以如何合理的管理Session,避免Session的频繁创建和销毁,对于提高系统的性能来说是非常重要的;
以往是通过eclipse的插件来自动完成这些代码的,当然效果是不错的。但代码过于冗长,维护困难。
Session是由SessionFactory负责创建的,而SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例;
那么Session是否是线程安全的呢? 不安全的。
Session中包含了数据库操作相关的状态信息,那么说如果多个线程同时使用一个Session实例进行CRUD,
就很有可能导致数据存取的混乱,你能够想像那些你根本不能预测执行顺序的线程对你的一条记录进行操作的情形吗?
在Session的众多管理方案中,我们今天来认识一种名ThreadLocal模式(在java1.2推出时支持的)的解决方案。
什么是ThreadLocal模式呢?
value:是openSession()生成的Session}
private Map values = Collections.synchronizedMap(new HashMap());
public Object get() {
Thread currentThread = Thread.currentThread();
Object result = values.get(currentThread);
if(result == null&&!values.containsKey(currentThread)) {
result = initialValue();
values.put(currentThread, result);
}
return result;
}
public void set(Object newValue) {
values.put(Thread.currentThread(), newValue);
}
public Object initialValue() {
return null;
}
}
具体如何利用ThreadLocal来管理Session?
public class HibernateUtil {
public static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static final ThreadLocal<Session>session=new ThreadLocal<Session>();
public static Session currentSession() throws HibernateException {
Session s = session.get();
if(s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = session.get();
if(s != null) {
s.close();
}
session.set(null);
}
}
借助上面的工具类获取Session实例,就可以实现线程范围内的Session共享,从而避免了线程中频繁的创建和销毁Session实例。
在用完后关闭Session对象。
也许大多数时候我们的DAO并不会涉及到多线程的情形,不会将DAO的代码写在Servlet之中,那样不是良好的 设计 ,
通常会在service层的代码里访问DAO的方法。
但是我还是建议采用以上的工具类来管理Session。