[转]利于ThreadLocal管理Hibernate Session
摘自http://aladdin.iteye.com/blog/40986
在利用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,用于存储每一个线程的变量的副本。比如下面的示例实现(为了简单,没有考虑集合的泛型):
1.public class ThreadLocal {
2. private Map values = Collections.synchronizedMap(new HashMap());
3. public Object get() {
4. Thread currentThread = Thread.currentThread();
5. Object result = values.get(currentThread);
6. if(result == null&&!values.containsKey(currentThread)) {
7. result = initialValue();
8. values.put(currentThread, result);
9. }
10. return result;
11. }
12. public void set(Object newValue) {
13. values.put(Thread.currentThread(), newValue);
14. }
15. public Object initialValue() {
16. return null;
17. }
18.}
那麽具体如何利用ThreadLocal来管理Session呢?Hibernate官方文档手册的示例之中,提供了一个通过ThreadLocal维护Session的好榜样:
1.public class HibernateUtil {
2. public static final SessionFactory sessionFactory;
3. static {
4. try {
5. sessionFactory = new Configuration().configure()
6. .buildSessionFactory();
7. } catch (Throwable ex) {
8. throw new ExceptionInInitializerError(ex);
9. }
10. }
11. public static final ThreadLocal<session></session> session =
12. new ThreadLocal<session></session>();
13. public static Session currentSession() throws HibernateException {
14. Session s = session.get();
15. if(s == null) {
16. s = sessionFactory.openSession();
17. session.set(s);
18. }
19. return s;
20. }
21. public static void closeSession() throws HibernateException {
22. Session s = session.get();
23. if(s != null) {
24. s.close();
25. }
26. session.set(null);
27. }
28.}
只要借助上面的工具类获取Session实例,我们就可以实现线程范围内的Session共享,从而避免了线程中频繁的创建和销毁Session实例。当然,不要忘记在用完后关闭Session。
写到这里,想再多说一些,也许大多数时候我们的DAO并不会涉及到多线程的情形,比如我们不会将DAO的代码写在Servlet之中,那样不是良好的设计,我自己通常会在service层的代码里访问DAO的方法。但是我还是建议采用以上的工具类来管理Session,毕竟我们不能仅仅考虑今天为自己做什么,还应该考虑明天为自己做什么!
[转]利于ThreadLocal管理Hibernate Session的更多相关文章
- spring管理hibernate session的问题探究
我们再用spring管理hibernate的时候, 我们会继承HibernateDaoSupport 或者HibernateTemplate类. 我们不知道这两个类之间有什么关系. 也没有去关闭ses ...
- [原创]java WEB学习笔记94:Hibernate学习之路---session 的管理,Session 对象的生命周期与本地线程绑定
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Hibernate事务管理-HibernateTransactionManager-对hibernate session的管理
由于对SSH还停留在比较初级的应用水平上,今天在遇到一个疑惑时折腾了很久,具体问题是这样的, 有这么一个测试方法, public static void test1() { ApplicationCo ...
- spring 管理事务配置时,结果 报错: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here这个异常
java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not al ...
- spring事务管理出错。No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy ...
- Hibernate Session & Transaction详解
Hibernate Session & Transaction详解 HIbernate中的Session Session是JAVA应用程序和Hibernate进行交互时使用的主要接口,它也是持 ...
- ThreadLocal管理Connection
ThreadLocal管理Connection 每一个用户都对应有一个单独线程,每一个线程都有一个数据库连接对象Connection对象接待它. 一个用户对应一个线程,这个线程中的Connection ...
- spring管理hibernate,mybatis,一级缓存失效原因
mybatis缓存:一级缓存和二级缓存 hibernate缓存:一级缓存和二级缓存 关于缓存: 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器, 其作用是为了减少应 ...
- 攻城狮在路上(壹) Hibernate(十八)--- 管理Hibernate的缓存
一般Session的缓存被称为Hibernate的第一级缓存,SessionFactory的外置缓存是一个可配置的缓存插件,称为Hibernate的第二级缓存.一.缓存的基本原理: 1.持久化层的缓存 ...
随机推荐
- 贝努利概率 matlab
参考:http://zhidao.baidu.com/link?url=3XZm35XpFf_kbADwDHEERtgFMKqHftiS5SyTCWcBtlF7B7zeNgoNqIzXxpJsHtBI ...
- gitlab The repository for this project is empty
/***************************************************************************** * gitlab The reposito ...
- dedecms 列表页 list 判断flag给定指定样式 (本地测试有效)
{dede:list pagesize='10'} [field:array runphp='yes'] if (@me['flag']=='a') @me=' <a class="n ...
- Java 父类和子类
package chapter11; public class GeometricObject1 { private String color="white"; private b ...
- the grave of my scripts
不定期更新.......... 1,fetch_seq.py https://github.com/freemao/AHRD/blob/master/fetch_seq.py 提取出你想要得染色体的某 ...
- 转 关于C#中派生类调用基类构造函数的理解
关于C#中派生类调用基类构造函数的理解 .c#class 本文中的默认构造函数是指在没有编写构造函数的情况下系统默认的无参构造函数 1. 当基类中没有自己编写构造函数时,派生类默认的调用 ...
- 66. Plus One
Given a non-negative number represented as an array of digits, plus one to the number. The digits ar ...
- codevs 1299 线段树 区间更新查询
1299 切水果 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 查看运行结果 题目描述 Description 简单的说,一共N个水果排成 ...
- 转:【Spring MVC Controller单例陷阱】
http://lavasoft.blog.51cto.com/62575/1394669/ Spring MVC Controller默认是单例的: 单例的原因有二:1.为了性能.2.不需要多例. 1 ...
- 渴切-开源中文css框架
渴切:是国内优秀的开源css框架. 渴切是一个开源中文 (X)HTML/CSS 框架 ,它的目的是减少你的css开发时间.它提供一个可靠的css基础去创建你的项目,能够用于网站的快速设计,通过重设和重 ...