Hibernate学习---Configuration,Session,SessionFactory Configuration:SessionFactory:Session:

上一节我们讲到了Hibernate的测试,并且给出了测试代码,刚开始看见这个测试代码的同学估计是一头雾水把,所以这一节我们来讲一下测试代码。 本节主要内容:

  • Configuration
  • SessionFactory
  • Session

首先我们再来看一下上一节的测试代码:

        //加载配置文件
        Configuration config = new Configuration().configure();
        //根据配置文件创建会话工厂
        SessionFactory factory = config.buildSessionFactory();
        //根据会话工厂创建会话
        Session session = factory.getCurrentSession();
        //创建一个事物对象
        Transaction tx = session.beginTransaction();
        //new 一个学生对象
        Student student = new Student("小三‰",19,99);
        //将对象持久化到数据表中
        session.save(student);
        //提交事务
        tx.commit();
        //关闭会话
        session.close();
        //关闭工厂
        factory.close();

Configuration:

首先是Configuration,它是用来解析我们配置的一个类,它加载配置的时候使用了这段代码:

Configuration config = new Configuration().configure();

看到这段代码的第一感觉是为啥还要在后面加一个方法,直接new一个Configuration不就行了吗,为啥还加了一个configure方法。 我们来打开源码瞧瞧:

public Configuration configure() throws HibernateException {
        return configure( StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME );
    }

看到了没,configure方法返回了一个有参的方法,且参数为: StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME 我们跟进去会发现这个参数是StandardServiceRegistryBuilder类定义的一个名字叫hibernate.config.xml的成员变量。 所以我们可以得出一个结论:如果你采用以下段代码来加载配置文件那么你的主配置文件名字必须叫作hibernate.config.xml Configuration config = new Configuration().configure(); 当然你也可以自定义,例如这样随意指定: Configuration config = new Configuration().configure("xxx.xml'); 但是我们建议使用hibernate指定的配置文件名。 这里我们只介绍这些,所以对于Configuration我们仅需要知道它是用来加载配置文件即可,以后具体分析,现在我们先将hibernate的基本原理讲明白就好。

SessionFactory:

SessionFactory factory = config.buildSessionFactory();

我们知道主配置文件里面最外面的便是<hibernate-configuration>接下来就是<session-factory>,所以通过Configuration实例对象的buildSessionFactory可以根据我们的配置文件建立会话工厂。值得注意的是SessionFactory是一个重量级的组件,是一个单例的,线程安全的。按理说单例对象一定是被共享的是线程不安全的,我们将它的实现类SessionFactoryimpl打开看发现它的大多数的成员变量都是final的,所以它是线程安全的。 一般SessionFactory实例都不进行关闭(开销太大),而是在应用结束的时候自动将其销毁。

Session:

session由SessionFactory的getCurrentSession()或者openSession()进行创建,在web应用中,每当有一个用户访问时就会为这个用户创建一个Session,所以Session是多例的,它包含了许多非final变量,对同一个用户可能会产生多个事务,若多事务同时对Session的同一个变量进行访问就会引起并发的问题从而导致线程不安全。

上面提到了Session的两种获取方式,接下来我们说一下两种方式的区别: getCurrentSession无论执行多少次只要是在同一个线程中它获取到的都是同一个Session对象,使用这个方法获取的Session对象是由ThreadLocal变量存储的(ThreadLocal在我的多线程文章里面有介绍),它的底层是一个Map,key就为线程的名字,所以用这个方法创建的Session对象是线程唯一的。 它创建Session对象的时候会进行判断,判断线程是是否已经存在session,如果不存在便进行创建。以下便是它的实现源码(有源码有真相):

    public Session getCurrentSession() throws HibernateException {
        if ( currentSessionContext == null ) {
            throw new HibernateException( "No CurrentSessionContext configured!" );
        }
        return currentSessionContext.currentSession();
    }

如果不存在那么久进行创建,底层也是通过openSession创建:

    protected Session buildOrObtainSession() {
        return baseSessionBuilder()
                .autoClose( isAutoCloseEnabled() )
                .connectionReleaseMode( getConnectionReleaseMode() )
                .flushBeforeCompletion( isAutoFlushEnabled() )
                .openSession();//就是这里
    }

具体的逻辑太多,不方便一直跟下去,所以有兴趣的可以一直跟下去。 openSession进行创建时,每执行一次便会创建一个Session对象,所以需要我们手动关闭,而getCurrentSession不用关闭。

getCurrentSession获得的Session对象不用注册便能够使用而openSession无需注册。

getCurrentSession获得的session对象一定要在事务里面执行,而openSession获得的对象可以不在事务里面执行。 以上就是对两种获取方式的简单总结。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IMWeb前端团队

上手 yeoman generator

最近折腾脚手架相关的一些事情。说到脚手架,不得不谈的就是yeoman了。 是什么 yeoman是一个脚手架生成工具。 yeoman generator则是yeo...

24450
来自专栏芋道源码1024

分布式消息队列 RocketMQ 源码分析 —— Message 拉取与消费(上)

摘要: 原创出处 http://www.iocoder.cn/RocketMQ/message-pull-and-consume-first/ 「芋道源码」欢迎...

38760
来自专栏大内老A

ASP.NET Core应用针对静态文件请求的处理[5]: DefaultFilesMiddleware中间件如何显示默认页面

DefaultFilesMiddleware中间件的目的在于将目标目录下的默认文件作为响应内容。我们知道,如果直接请求的就是这个默认文件,那么前面介绍的Stat...

20850
来自专栏JavaEE

Java面试题 - 03前言:三、框架篇:

1. JDBC编程有什么不足?mybatis是如何解决的? 答:主要有以下几个方面:

11110
来自专栏Python爬虫与算法进阶

或许你应该学学 postman

使用 最简单的方法就是直接在浏览器中复制 Copy as cURL ,然后把数据导入 postman,然后 send ,收工。 我们这里拿 知乎首页 举例 ?...

35350
来自专栏Fundebug

Source Map入门教程

部署前端之前,开发者通常会对代码进行打包压缩,这样可以减少代码大小,从而有效提高访问速度。然而,压缩代码的报错信息是很难Debug的,因为它的行号和列号已经失真...

27260
来自专栏青玉伏案

iOS开发之再探多线程编程:Grand Central Dispatch详解

Swift3.0相关代码已在github上更新。之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread、操作队列以及GCD,介绍的不够深入。今...

20470
来自专栏进击的程序猿

php异常处理 之 BooBoo库介绍

本文介绍php开源库BooBoo,是一个处理php异常和错误的开源库,通过简单的分析代码,我们知道了实际项目中怎么正确的设置错误和异常。

11020
来自专栏c#开发者

Msmq设计文档(赋源代码)

Msmq设计文档 文件状态: [√] 草稿 [ ] 正式发布 [ ] 正在修改 文件标识: ECI-MSMQ v01 当前版本: 0.5...

36080
来自专栏繁花云

Apache默认编码修改

但是PHP文件一运行就闷逼了,显示出来的文字都是乱码,但是源码那么多,一个个改是不可能了。

13700

扫码关注云+社区

领取腾讯云代金券