在利用Hibernate开发DAO模块时,我们和Session打的交道最多,所以如何合理的管理Session,避免Session的频繁创建和销
毁,对于提高系统的性能来说是非常重要的,以往是通过eclipse的插件来自动完成这些代码的,当然效果是不错的,但是总是觉得不爽(没有读懂那些冗长
的代码),所以现在打算自己实现Session管理的代码。我们知道Session是由SessionFactory负责创建的,而
SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例,那么
Session是否是线程安全的呢?很遗憾,答案是否定的。Session中包含了数据库操作相关的状态信息,那么说如果多个线程同时使用一个
Session实例进行CRUD,就很有可能导致数据存取的混乱,你能够想像那些你根本不能预测执行顺序的线程对你的一条记录进行操作的情形吗?
在Session的众多管理方案中,我们今天来认识一种名为ThreadLocal模式的解决方案。
早在Java1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新
的选择。ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread
local
variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,
就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每
一个线程都完全拥有一个该变量。
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。比如下面的示例实现(为了简单,没有考虑集合的泛型):
- public
class
ThreadLocal {
-
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呢?Hibernate官方文档手册的示例之中,提供了一个通过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 =
-
new
ThreadLocal();
-
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,毕竟我们不能仅仅考虑今天
为自己做什么,还应该考虑明天为自己做什么!
分享到:
相关推荐
NULL 博文链接:https://qixiaopeng.iteye.com/blog/551764
今天小编就为大家分享一篇关于Hibernate用ThreadLocal模式(线程局部变量模式)管理Session,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>(); private static Configuration configuration = new Configuration(); private static org.hibernate.SessionFactory ...
ThreadLocal入门教程。 讲解了线程安全和ThreadLocal的使用的基本知识。
ThreadLocal
通向架构师的道路(第七天)之漫谈使用ThreadLocal改进你的层次的划分
理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal
ThreadLocal应用示例及理解,这个写了相关的示例,可以参考一下。
学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!
session的丢失原因和解决方案,与viewstate和cookie 的区别
正确理解ThreadLocal.pdf
hibernate HQL 查询教程 管理 Session ThreadLocal 接口的使用
DbUTils中用ThreadLocal类
主要介绍ThreadLocal的原理,实例分析以及注意事项
java 简单的ThreadLocal示例
ThreadLocal的几种误区ThreadLocal的几种误区ThreadLocal的几种误区
Synchronized与ThreadLocal
本例以序列号生成的程序为例,展示ThreadLocal的使用
ThreadLocal保证一个类的实例变量在各个线程中都有一份单独的拷贝, 从而不会影响其他线程中的实例变量