Configuration

Configuration 主要用于启动、加载和管理 Hibernate 的配置文件信息,在启动 Hibernate 的过程中,Configuration 实例首先确定 Hibernate 文件的位置,然后读取相关配置,最后创建一个唯一的 SessionFactory 实例。

Hibernate 通常使用 Configuration config=new Configuration().configure(); 的方式创建实例,此种方式默认会在 src 下读取 hibernate.cfg.xml 配置文件。如果不希望配置文件放置在 src 目录下,则可以在 configure() 方法中传入一个参数指定文件位置,其代码如下所示:
Configuration config = new Configuration().configure("文件的位置");

此种写法中 Hibernate 会到指定的位置查询配置文件。例如,读取 src 下 config 包中的 hibernate.cfg.xml 文件,可以将代码写成如下形式:
Configuration config = new Configuration().configure("/config/hibernate.cfg.xml");

需要注意的是,Configuration 对象只存在于系统的初始化阶段,它将 SessionFactory 创建完成后,就完成了自己的使命。

SessionFactory

SessionFactory 接口负责读取并解析映射文件,以及建立 Session 对象,它在 Hibernate 中起到一个缓冲区的作用,会将 Configuration 对象中的所有配置信息、Hibernate 自动生成的 SQL 语句以及某些可重复利用的数据加载到缓冲区中。同时,它还维护了 Hibernate 的二级缓存。

通常所使用的 SessionFactory 实例是通过 Configuration 对象获取的,其获取方法如下所示:
SessionFactory sessionFactory = config.buildSessionFactory();

SessionFactory 具有以下特点。
它是线程安全的,它的同一个实例能够供多个线程共享。
它是重量级的,不能随意创建和销毁它的实例。

由于 SessionFactory 是一个重量级的对象,占用的内存空间较大,所以通常情况下,一个应用程序只需要一个 SessionFactory 实例,只有应用中存在多个数据源时,才为每个数据源建立一个 SessionFactory 实例。为此,在实际开发时,通常会抽取出一个工具类提供 Session 对象。下面就介绍一个简单的抽取方式,如下所示。
图片说明
上述代码中,首先声明了一个私有的静态 final 类型的 Configuration 对象和 SessionFactory 对象,供类中的其他成员使用,下面通过静态方法构建了 SessionFactory 实例,最后提供了一个公有的静态方法供外部获取 session 对象。使用此工具类,就可以直接通过 HibernateUtils.getSession() 的方式获取 session 对象。

Session

Session 是 Java 应用程序和 Hibernate 进行交互时所使用的主要接口,是持久化操作的核心 API。它主要用于读取、创建和删除映射对象的实例,这一系列的操作将被转换为数据表中的增加、修改、查询和删除操作。

Session 是轻量级的,实例的创建和销毁不需要消耗太多的资源,同时它还是 Hibernate 的一级缓存,这个缓存主要用于存放当前工作单元加载的对象。

获取 Session 实例有两种方式,一种是通过 openSession() 方法,另一种是通过 getCurrentSession() 方法。两种方法获取 Session 的代码如下所示:
图片说明
以上两种获取 Session 实例的主要区别是:采用 openSession() 方法获取 Session 实例时,SessionFactory 直接创建一个新的 Session 实例,并且在使用完成后需要调用 close() 方法进行手动关闭;而 getCurrentSession() 方法创建的 Session 实例会被绑定到当前线程中,它在提交或回滚操作时会自动关闭。

在 Session 中,提供了多个持久化的操作方法,其常用方法如表 1 所示。

图片说明
需要注意的是,Session 是线程不安全的,当多个并发线程同时操作一个 Session 实例时,就可能导致 Session 数据存取的混乱(当方法内部定义和使用 Session 时,不会出现线程问题)。因此设计软件架构时,应避免多个线程共享一个 Session 实例。

Transaction

Transaction 接口主要是用于管理事务,它是 Hibernate 的数据库事务接口,且对底层的事务接口进行了封装。Transaction 接口的实例对象是通过 Session 对象开启的,其开启方式如下所示:
Transaction transaction = session.beginTransaction();

在 Transaction 接口中,提供了事务管理的常用方法,具体如下。
commit() 方法:提交相关联的 session 实例。
rollback() 方法:撤销事务操作。
wasCommitted() 方法:检查事务是否提交。

当应用程序执行完持久化操作后,需要调用 commit() 方法提交事务,或者调用 rollback() 方法回滚事务(取消事务),可以通过以下代码加以理解:
图片说明
从上述代码中可以看出,Session 执行完保存操作后,使用了 Transaction 接口的 commit() 方法进行事务提交。只有事务执行提交后,才能真正地将数据操作同步到数据库中。在发生异常时,需要使用 rollback() 方法进行事务回滚,以避免数据发生错误。

Query

Query 接口是 Hibernate 的查询接口,主要用于执行 Hibernate 的查询操作。Query 中包装了一个 HQL(Hibernate Query Language)查询语句,该语句采用了面向对象的查询方式,具有丰富灵活的查询特征。因此,Hibernate 官方推荐使用 HQL 语言进行查询。
在 Hibernate 中,使用 Query 对象的步骤如下。
获得 Hibernate Session 对象。
编写 HQL 语句。
调用 session.createQuery 创建查询对象。
如果 HQL 语句包含参数,则调用 Query 的 setXxx 设置参数。
调用 Query 对象的 list() 或 uniqueResult() 方法执行查询。

了解了使用 Query 对象的步骤后,接下来通过具体示例演示 Query 对象的查询操作。

1)向 user 表中插入 4 条数据,插入数据的 SQL 语句如下所示:
图片说明
插入后,user 表中的数据如图 1 所示。
user表中的数据
图片说明

2)在 com.mengma.test 包中创建一个名称为 QueryTest 的类,在类中添加一个名称为 testFindAll() 的方法,编辑后如下所示。
图片说明
上述代码中,按照 Query 对象的使用步骤,对 user 表的数据进行了查询。使用 Junit 运行测试方法成功后,执行结果如图 2 所示。

Query查询输出结果
图 2 Query 查询输出结果

从图 2 中可以看出,user 表中的数据已经全部被查询并输出。

在 Query 接口中,除了上面代码中使用的 list() 方法以外,还包含其他一些常用方法,如表 2 所示。

图片说明

Criteria

Criteria 接口是 Hibernate 提供的一个面向对象的查询条件接口,通过它完全不需要考虑数据库底层如何实现,以及 SQL 语句如何编写。Criteria 查询又称为 QBC 查询(Query By Criteria),是 Hibernate 的另一种对象检索方式。

一个单独的查询就是 Criterion 接口的一个实例,用于限制 Criteria 对象的查询,在 Hibernate 中 Criterion 对象的创建通常是通过 Restrictions 工厂类完成的,它提供了一系列的条件查询方法,如表 3 所示。
图片说明
这个方法通常情况下,使用 Criteria 对象查询数据的主要步骤如下。

1)获得 Hibernate 的 Session 对象。

2)通过 Session 获得 Criteria 对象。

3)使用 Restrictions 的静态方法创建 Criterion 条件对象。Restrictions 类中提供了一系列用于设定查询条件的静态方法,这些静态方法都返回 Criterion 实例,每个 Criterion 实例代表一个查询条件。

4)向 Criteria 对象中添加 Criterion 查询条件。Criteria 的 add() 方法用于加入查询条件。

5)执行 Criteria 的 list() 或 uniqueResult() 获得结果。

了解了 Criteria 对象的使用步骤后,下面通过案例演示如何使用 Criteria 对象实现查询操作。在 hibernateDemo01 项目的 com.mengma.test 包中新建一个名称为 CriteriaTest 的类,在类中添加一个名称为 testQBC() 的方法,如下所示。
图片说明
上述代码中,按照 Criteria 对象查询数据的步骤查询了 user 表中 name 等于 zhangsan 的数据。使用 JUnit 测试运行 testQBC() 方法后,控制台的显示结果如图 3 所示。

从图 3 中可以看到,使用 Criteria 对象的查询方法,已将数据表中“name="zhangsan"”的数据查询输出。

使用Criteria条件查询
图 3 使用Criteria条件查询
图片说明