import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder; @SuppressWarnings("deprecation")
public class HibernateSessionFactory { /**
* Location of hibernate.cfg.xml file.
* Location should be on the classpath as Hibernate uses
* #resourceAsStream style lookup for its configuration file.
* The default classpath location of the hibernate config file is
* in the default package. Use #setConfigFile() to update
* the location of the configuration file for the current session.
*/ private static String CONFIG_FIEL_LOACTION = "/hibernate.cfg.xml";
private static String configFile = CONFIG_FIEL_LOACTION;
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static org.hibernate.SessionFactory sessionFactory;
private static Configuration configuration = new Configuration();
private static ServiceRegistry serviceRegistry; /**
在回话工厂类HibernateSessionFactory中, 首先通过一次静态代码块来启动Hibernate,该代码块只在HibernateSessionFactory类被加载时执行一次,用于建立sessionFactory。即SessionFactory是线程安全的,只能被实例化一次。
在静态代码块中通过创建Configuration对象并调用其configure()方法读取Hibernate配置文件hibernate.cfg.xml信息,从而进行配置信息的管理。然后
创建SessionFactory实例,在Hibernate4.0版本之前,该实例创建工作由Configuration对象的buildSessionFactory()方法来完成。而Hibernater4.0版本之后,创建SessionFactory实例的方法有所改变,Hibernate 增加了一个注册ServiceRegistryBuilder类。要生成一个注册机对象,然后所有的生成
SessionFactory的对象向注册机注册一下再使用。生成方法还config.buildSessionFactory()方法,只不过加了一个注册机的参数。
*/
static {
try {
configuration.configure();
serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%" + e);
e.printStackTrace();
}
} private HibernateSessionFactory() {
} /**
* Returns the ThreadLocal Session instance. Lazy initialize
* the <code>SessionFactory</code> if needed.
*
* 由于sessionFactory是线程安全的,因而同一个SessionFactory实例可以被多个线程共享,即多个并发线程可以同时访问一个SesisonFactory并
* 获得Session的实例。但由于Session不是线程安全的,如果多个并发线程同时操作同一个Session对象,就可能出现一个线程在进行数据库操作,而另一个
* 线程将Session对象关闭的情况,从而出现异常。如何才能保证线程安全呢?这就要求SessionFactory能够针对不同的线程创建不同的Session对象,即
* 需要对Session进行有效的管理,Hibernate中使用ThreadLocal对象来维护和管理Session实例。
*
* ThreadLocal是线程局部变量,线程局部变量高效的为每一个使用它的线程提供单独的线程局部变量的副本。为了实现为每个线程维护一个变量的副本,ThreadLocal
* 类提供了一个Map结构,是key值用来保存线程的ID, value用来保存一个Session实例的副本。这样多线程并发操作时,实在与自己绑定的Session实例副本上进行
* 的,从而避免多个线程横在同一个Session实例上操作是可能导致的数据异常。
*
* 在HibernaterSessionFctory类的getSession()方法中,首先调用ThreadLocal类的get()方法获得当前线程的Session对象,然后判断当前线程是否已存在
* Session对象或者对象未打开,在判断SessionFactory对象是否为空,如果SeesionFctory对象不存在,先调用rebuildSessionFactory()方法创建SesionFactory,
* 如果SessionFactory对象已经存在,则调用SessionFactory对象的openSession()方法创建Session对象。创建完Session对象后,还需要调用ThreadLocal的set()
* 方法为该线程保存Session对象。
*
* @return Session
* @throws HibernateException
*/
public static Session getSession() {
Session session = (Session) threadLocal.get();
try{
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
} catch (HibernateException e){
System.err.println("%%%% Error Creating getSession %%%%" + e);
e.printStackTrace();
}
return session;
} /**
* Rebuild hibernate session factory
*
*/
public static void rebuildSessionFactory() {
synchronized(sessionFactory){
try {
configuration.configure(configFile);
serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
System.err.println("%%%% Error rebuildSessionFactory %%%%" + e);
e.printStackTrace();
}
}
} /**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession(){
Session session = (Session) threadLocal.get();
threadLocal.set(null);
try{
if (session != null && session.isOpen()) {
session.close();
}
} catch(HibernateException e){
System.err.println("%%%% Error closeSession %%%%" + e);
e.printStackTrace();
}
} /**
* return session factory
*
*/
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* return hibernate configuration
*
*/
public static Configuration getConfiguration() {
return configuration;
} public static void setConfigFile(String configFile){
HibernateSessionFactory.configFile = configFile;
} }

Hibernate4.0之HibernateSessionFactory源码详解的更多相关文章

  1. Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解

    Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解 今天主要理一下StreamingContext的启动过程,其中最为重要的就是Jo ...

  2. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  3. 条件随机场之CRF++源码详解-预测

    这篇文章主要讲解CRF++实现预测的过程,预测的算法以及代码实现相对来说比较简单,所以这篇文章理解起来也会比上一篇条件随机场训练的内容要容易. 预测 上一篇条件随机场训练的源码详解中,有一个地方并没有 ...

  4. [转]Linux内核源码详解--iostat

    Linux内核源码详解——命令篇之iostat 转自:http://www.cnblogs.com/york-hust/p/4846497.html 本文主要分析了Linux的iostat命令的源码, ...

  5. saltstack源码详解一

    目录 初识源码流程 入口 1.grains.items 2.pillar.items 2/3: 是否可以用python脚本实现 总结pillar源码分析: @(python之路)[saltstack源 ...

  6. Shiro 登录认证源码详解

    Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加 ...

  7. udhcp源码详解(五) 之DHCP包--options字段

    中间有很长一段时间没有更新udhcp源码详解的博客,主要是源码里的函数太多,不知道要不要一个一个讲下去,要知道讲DHCP的实现理论的话一篇博文也就可以大致的讲完,但实现的源码却要关心很多的问题,比如说 ...

  8. Activiti架构分析及源码详解

    目录 Activiti架构分析及源码详解 引言 一.Activiti设计解析-架构&领域模型 1.1 架构 1.2 领域模型 二.Activiti设计解析-PVM执行树 2.1 核心理念 2. ...

  9. 源码详解系列(六) ------ 全面讲解druid的使用和源码

    简介 druid是用于创建和管理连接,利用"池"的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制.连接可靠性测试.连接泄露控制.缓存语句等功能,另外,druid还扩展 ...

随机推荐

  1. dvb标准

    一.概念 DVB, 数字视频广播Digital Video Broadcasting的缩写, 是由DVB项目维护的一系列国际承认的数字电视公开标准.(欧标)二.分类DVB系统传输方式有如下几种: 卫星 ...

  2. python RecursionError: maximum recursion depth exceeded in comparison错误

    处理快速排序,递归深度可能非常大,而系统默认的深度可能没有这么大 需要设置最大递归深度 import sys sys.setrecursionlimit(100000) # 这个值的大小取决你自己,最 ...

  3. getComputedStyle的应用

    后面有例子,所以把HTML,CSS样式写在前面 HTML结构: <div id="myDiv" style="background-color: lightseag ...

  4. MySQL5.6 GTID新特性实践

    MySQL5.6 GTID新特性实践 GTID简介 搭建 实验一:如果slave所需要事务对应的GTID在master上已经被purge了 实验二:忽略purged的部分,强行同步 本文将简单介绍基于 ...

  5. 关于Java8函数式编程你需要了解的几点

    函数式编程与面向对象的设计方法在思路和手段上都各有千秋,在这里,我将简要介绍一下函数式编程与面向对象相比的一些特点和差异. 函数作为一等公民 在理解函数作为一等公民这句话时,让我们先来看一下一种非常常 ...

  6. 多文档上传(upload multiple documents)功能不能使用怎么办?

    问题描述: 在SharePoint 2010的文档库里选择documents标签,然后选择upload document下拉菜单,你会发现upload multiple documents那个按钮是灰 ...

  7. 介绍.NET 开发必备工具 .NET Portability Analyzer

    随着.NET的原来越开放,不仅仅是开源这么简单了,也意味着.NET程序员要关注越来越多的平台,涵盖.NET Mic Framework, Xamarin,Mono,.NET等等,从windows到li ...

  8. 我的第一段jQuery代码

    说起 jQuery,很多人可能觉得,不算什么,就是个js类库.而,对于我,下面这几行代码,是一个新的开始. 多年来,我一直在使用MooTools ,他面向对象,写起来结构清晰分明,都是在原生js的基础 ...

  9. GIT常用命令笔记

    最近在做了一个自己的项目.两个人合作的,所以需要用到版本管理工具.本来打算学一下自己搭建svn的,后来朋友推荐我用git,免费,流行,好用,逼格.所以就学习了一下.发现这个git与已经使用惯了的svn ...

  10. CSS尺寸和字体单位-em、px还是%

    在页面整体布局中,页面元素的尺寸大小(长度.宽度.内外边距等)和页面字体的大小也是重要的工作之一.一个合理设置,则会让页面看起来层次分明,重点鲜明,赏心悦目.反之,一个不友好的页面尺寸和字体大小设置, ...