`
caoyinghui
  • 浏览: 125704 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

HibernateSessionFactory创建的Session是否单例

阅读更多

使用Eclipse生成Hibernate 代码时候工具为我们生成了一个 HibernateSessionFactory 这样的类 来为我们提供获得Session的方法. 但是用这个类的时候我们发现一个问题. 看下面代码

        Session session1= HibernateSessionFactory.getSession();      
        Session session2 = HibernateSessionFactory.getSession();
        System.out.println(session1+"__"+session2);
        System.out.print(session1==session2);

 

通过测试发现 session1==session2 结果为 true .  难道真的是单例的吗?

我们来看一下HibernateSessionFactory 中 getSession()的实现

 

public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();

        if (session == null || !session.isOpen()) {
            if (sessionFactory == null) {
                rebuildSessionFactory();
            }
            session = (sessionFactory != null) ? sessionFactory.openSession()
                    : null;
            threadLocal.set(session);
        }

        return session;
    }

 

在这个方法中我们看这样两行代码

1,Session session = (Session) threadLocal.get();

2,threadLocal.set(session);

这两行代码中 HibernateSessionFactory  在获得 session的时候是先去threadLocal上取 如果取到了就直接返回,取不到就 生成一个 并 通过set注册到当前线程上.

再来看一下 ThreadLocal 中 get ,set 的实现;

 

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            return (T)map.get(this);

        // Maps are constructed lazily.  if the map for this thread
        // doesn't exist, create it, with this ThreadLocal and its
        // initial value as its only entry.
        T value = initialValue();
        createMap(t, value);
        return value;
    }
 
public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

 

从它的get,set方法的实现中我们可以看出ThreadLocal 是以一种单例注册表的机制(一个单例类中包含一组对象的聚集) 实现的 通过它的实现(createMap(t,value)) 我们可以发现. 它保证在一个线程上只能注册一个实例. 并且每个线程上可以注册一个实例.因为不同的线程下Thread t = Thread.currentThread();
                                                                                     ThreadLocalMap map = getMap(t);

代表不同的对象 如果 t 是一个新的线程 那么 或的的map就是为空的 . 所以 createMap(t,value) 就会把一个新的实例放到这个线程上.并注册到注册表(ThreadLocalMap)中.

也就是说如果你在多个线程下创建了多个session 那么这些session在没有关闭的情况下都被保存在注册表(ThreadLocalMap)中 . ThreadLocalMap 中保存的就是一组这样的session对象.而不是一个.

下面是一个测试用来证明这一点.: 

 

class MySessionTest implements java.lang.Runnable{
    Session session=null;
    public void run()...{
        session= HibernateSessionFactory.getSession();    
        System.out.println("创建完毕"+Thread.currentThread()+"::"+session);
    }
    
    public Session getSesssionByThread(){
        return session;
    }
}

 

 在main方法中写.

 

 MySessionTest t1 = new MySessionTest();
        MySessionTest t2 = new MySessionTest();
        Thread tt1 = new Thread(t1);
        Thread tt2 = new Thread(t2);
        tt1.start();
        tt2.start();
        
        tt1.sleep(1000);
        tt2.sleep(1000);
        Thread.sleep(1000);
        //如果线程不睡眠 下面的语句会先执行 得不到正确的结果. 只有等t1 ,和 t2 将session创建完毕后才能输出.    
        System.out.println(t1.getSesssionByThread()==t2.getSesssionByThread());

 

通过测试发现 输出结果为false   也就证明了 在多线程环境下HibernateSessionFactory.getSession()创建的Session不是单例的 .

但是又遇到了一个问题. 假设我要在同一个线程上通过HibernateSessionFactory获得多个Session的实例怎么办呢?

我们不妨在HibernateSessionFactory 中自己扩展一个方法

 

public static Session getAnotherSession() throws HibernateException{
        if (sessionFactory == null) {
            rebuildSessionFactory();
        }
        return sessionFactory.openSession();
              
    }

 

通过这个方法获得的session实例 都上重新创建的新的势力.

看下面的测试代码

 

 Session session1= HibernateSessionFactory.getSession();    
        Session session2 = HibernateSessionFactory.getAnotherSession();    
        Session session3 = HibernateSessionFactory.getAnotherSession();    
        
        
        System.out.println(session1==session2);
        System.out.println(session2==session3);
  

输出的结果为false ,false ; 也就是在同一线程下获得了3个不同的session实例.

 因为HIbernateSessionFactory是单例的所以创建的SessionFactory也是单例的 .保证 SessionFactory 不被重复加载 ,而且扩展的这个方法.处在HIbernateSessionFactory 也不会重新去加载SessionFactory .

Eclipse为什么要把这个HIbernateSessionFactory获得的这个session定义为一个线程上只有一个实例呢?

个人认为:

1,session 在缓存在操作数据的时候应该具有隔离性. 也就是尽可能的将你要操做的一组数据放到同一个 session  缓存中 ,这样不至于在清理缓存的时候出现数据更新紊乱的情况.

2,session 不是线程安全的 , 在设计时候应该尽可能的避免多个线程共享一个session . 但又不能把session定义为单例. 所以就以一个线程上最多只能创建一个session实例 .并且每个线程都能创建一个实例.的这样一种单例注册表的机制来实现 .

关于单例类和单例注册表 可以参看我的另一片文章

http://blog.csdn.net/caoyinghui1986/archive/2008/05/22/2468180.aspx

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/caoyinghui1986/archive/2008/05/24/2476162.aspx

分享到:
评论

相关推荐

    大、小断层矿井小波SVM融合智能故障预测matlab代码.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    垂直SeekBar(拖动条).zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    libADLMIDI1-1.5.0-bp153.1.1.x86-64.rpm

    libADLMIDI1-1.5.0-bp153.1.1.x86_64.rpm 是用于在 x86_64 架构的设备上安装的 RPM 包,具体功能如下: 名称:libADLMIDI1 版本:1.5.0 摘要:带有 OPL3 (YMF262) 模拟器的软件 MIDI 合成器库 许可证:GPL-3.0-only 和 LGPL-3.0-only 该库提供了一个基于 ADLMIDI 的软件 MIDI 合成器,它模拟了 OPL3 音源芯片(FM 合成)。它可以通过使用 ADLMIDI 库来实现多平台的 MIDI 播放和 OPL3 模拟。 该 RPM 包适用于 x86_64 架构,用于在相关设备上安装 libADLMIDI1 库文件。库文件包括: /usr/lib64/libADLMIDI.so.1 和 /usr/lib64/libADLMIDI.so.1.5.0:库文件 /usr/share/doc/packages/libADLMIDI1/AUTHORS、/usr/share/doc/packages/libADLMIDI1/README.md 等文档文件:文档文件

    基于qt+C++实现u盘插拔检测.+源码(毕业设计&课程设计&项目开发)

    基于qt+C++实现u盘插拔检测.+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于qt+C++实现u盘插拔检测.+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于qt+C++实现u盘插拔检测.+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于qt+C++实现u盘插拔检测.+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~

    Quectel_Product_Brochure_CN_V7.9.pdf

    Quectel_Product_Brochure_CN_V7.9.pdf

    更换软件主题(apk方式).zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    chepai-reg-main (2).zip

    phpstudy

    Python 入门详细教程-1天学会 Python.docx

    python入门

    二维码扫描的实现.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    移动机器人机械臂的设计开题报告.doc

    移动机器人机械臂的设计开题报告.doc

    基于QT+C++开发的智能平台访客系统+源码

    用法链接:https://menghui666.blog.csdn.net/article/details/137977678?spm=1001.2014.3001.5502 基于QT+C++开发的智能平台访客系统+源码,包含主界面、系统设置、警情查询、调试帮助、用户退出功能。 基于QT+C++开发的智能平台访客系统+源码,包含主界面、系统设置、警情查询、调试帮助、用户退出功能。 基于QT+C++开发的智能平台访客系统+源码,包含主界面、系统设置、警情查询、调试帮助、用户退出功能。

    三菱机械臂校点说明.pptx

    三菱机械臂校点说明.pptx

    按字母索引滑动.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    激光推送客户端demo.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    c语言入门,小白进军C语言.zip

    C语言诞生于美国的贝尔实验室,由丹尼斯·里奇(Dennis MacAlistair Ritchie)以肯尼斯·蓝·汤普森(Kenneth Lane Thompson)设计的B语言为基础发展而来,在它的主体设计完成后,汤普森和里奇用它完全重写了UNIX,且随着UNIX的发展,c语言也得到了不断的完善。为了利于C语言的全面推广,许多专家学者和硬件厂商联合组成了C语言标准委员会,并在之后的1989年,诞生了第一个完备的C标准,简称“C89”,也就是“ANSI C”,截至2020年,最新的C语言标准为2018年6月发布的“C18”。 [5] C语言之所以命名为C,是因为C语言源自Ken Thompson发明的B语言,而B语言则源自BCPL语言。 1967年,剑桥大学的Martin Richards对CPL语言进行了简化,于是产生了BCPL(Basic Combined Programming Language)语言。

    Python入门到精通.zip

    python入门 单元测试和测试用例 Python标准库中的模块unittest提供了代码测试工具。 单元测试用于核实函数的某个防霾呢没有问题; 测试用例是一组单元测试,这些单元测试仪器一起核实函数在各种情形下的行为都符合要求。良好的测试用例考虑到了函数可能收到的各种收入,包含所有针对这些情形的测试。 全覆盖式测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。 对于大型项目,要实现全覆盖可能很难。通常,最初只要对针对代码的重要行为编写测试即可,等项目给广泛使用时再考虑全覆盖。 可通过的测试 创建测试用例的语法需要一段时间才能习惯,但测试用例创建后,再添加针对函数的单元测试就很简单了。要为函数编写测试用例,可先导入模块unittest以及要测试的函数,在创建一个继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试。 下面test_name_function.py一个只包含一个方法的测试用例,它检查函数get_formatted_name()在给定名和姓时能否正确的工作。

    基于matlabbenders分解算法.zip

    基于matlabbenders分解算法.zip

    dsp工程设计讲座.ppt

    dsp工程设计讲座.ppt

    Adams空间复杂机械臂动力学仿真研究.doc

    Adams空间复杂机械臂动力学仿真研究.doc

    基于Android+OpenCV的车牌识别系统源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 基于Android+OpenCV的车牌识别系统源码+使用文档+全部资料(优秀项目).zip基于Android+OpenCV的车牌识别系统源码+使用文档+全部资料(优秀项目).zip基于Android+OpenCV的车牌识别系统源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

Global site tag (gtag.js) - Google Analytics