使用ThreadLocal编写HibernateUtil工具类
来源:互联网 发布:自学java知乎 编辑:程序博客网 时间:2024/05/17 07:09
一、问题的提出
我们知道Session是由SessionFactory负责创建的,而SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例,而Session不是线程安全的。Session中包含了数 据库操作相关的状态信息,那么说如果多个线程同时使用一个Session实例进行CRUD,就很有可能导致数据存取的混乱,你能够想像那些你根本不能预测 执行顺序的线程对你的一条记录进行操作的情形吗?
二、 解决方案思路(使用Threadlocal类集合)
早在Java1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新 的选择。ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。 线程局部变量(ThreadLocal)其实的功用非常简单, 就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每 一个线程都完全拥有一个该变量。 ThreadLocal这个类本身不是代表线程要访问的变量,这个类的成员变量才是。JDK1.5给ThreadLocal加了泛型功能,即是 ThreadLocal,这个泛型T即是要线程的本地变量。线程通过ThreadLocal的get和set方法去访问这个变量T。 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; } }
三、解决方案步骤
在HibernateUtil类中我们需要定义一个静态的成员变量用于保存当前线程共用的Session,下面是HibernateUtil.java示例代码:
package ecnu.sgy.Ch5;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.hibernate.service.ServiceRegistry;import org.hibernate.service.ServiceRegistryBuilder;public class HibernateUtil { private static final SessionFactory sessionFactory; // 使用ThreadLocal集合保存当前业务线程中的SESSION private static ThreadLocal<Session> threadLocalSession = new ThreadLocal<Session>(); static { //第一步,获取heibernate.cfg.xml的配置信息 Configuration config = new Configuration().configure(); //第二步,创建服务注册构建器对象,将对象中加载所有的配置信息存放到注册服务中 ServiceRegistryBuilder serviceRegistryBuilder = new ServiceRegistryBuilder() .applySettings(config.getProperties()); //第三步,创建注册服务 ServiceRegistry serviceRegistry = serviceRegistryBuilder .buildServiceRegistry(); //第四步,创建SessionFactory sessionFactory = config.buildSessionFactory(serviceRegistry); } //单列模式,构造函数私有 private HibernateUtil() { } //获取实例 public HibernateUtil getInstance(){ return new HibernateUtil(); } //获取session factory public static SessionFactory getSessionFactory() { return sessionFactory; } //从SessionFactory中获取Session public static Session getSession(){ //获取当前线程下的Session Session session = threadLocalSession.get(); //如果Session不存在,则创建 if(session==null){ session = getSessionFactory().getCurrentSession(); //放入当前线程的容器中保存 threadLocalSession.set(session); } return session; } public static void closeSession(){ Session session = threadLocalSession.get(); if(session!=null){ // session.close();//这里无需将Session关闭,因为该Session是保存在当前线程中的,线程执行完毕Session自然会销毁 threadLocalSession.set(null); } }}
*****************************
说明:
关于getCurrentSession()方法:
sessionFactory.getCurrentSession()获取当前线程中的Session, 当调用时,hibernate将session绑定到当前线程,事务结束后,hibernate将session从当前线程中释放,并且关闭 session。当再次调用getCurrentSession()时,将得到一个新的session,并重新开始这一系列工作。这样调用方法如下: Session session = HibernateUtil.getSessionFactory().getCurrentSession();
getCurrentSession和openSession的区别:
1、getCurrentSession创建的session会和绑定到当前线程,而openSession不会。
2、getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,而openSession必须手动关闭
3、getCurrentSession需在在Hibernate.cfg.xml文件中添加配置:
thread
0 0
- 使用ThreadLocal编写HibernateUtil工具类
- HibernateUtil工具类的编写
- HibernateUtil ThreadLocal
- HibernateUtil 工具类
- HibernateUtil工具类
- Session工具类:HibernateUtil
- HibernateUtil 工具类
- HibernateUtil工具类
- HibernateUtil工具类回顾
- HibernateUtil工具类
- HibernateUtil工具类的写法
- HibernateUtil 获取session工具类
- hibernateUtil工具类的封装
- 【SSH三大框架】Hibernate基础第二篇:编写HibernateUtil工具类优化性能
- netbean 的 hibernateUtil 类编写的问题
- hibernate4之后HibernateUtil类的编写
- 深入研究java.lang.ThreadLocal类,以HibernateUtil为实例
- HibernateUtil.java 工具类(获得SESSION)
- linux 下Python调用C模块
- [游戏与人生]推荐几款老单机游戏
- 给无符号数赋值负数(有符号数)的理解(unsigned\signedf)
- UIVie和CALayer属性对应关系
- IOS UItextfield 和 UItextView 键盘隐藏
- 使用ThreadLocal编写HibernateUtil工具类
- swift笔记之新项目中navigationController的创建和初始化
- 正益工场,构建社区型移动众包平台
- oracle数据库创建用户和IAR编译器读取数据的问题
- Mysql中查找并删除重复数据的方法
- http响应状态码测试脚本(python版)
- STL算法库-排序和相关操作(一)
- Codeforces Round #336 (Div. 2)B. Hamming Distance Sum
- windows7下eclipse连接ubuntu中的hadoop开发环境配置