Configuration、SessionFactory、Session、Transaction、Query和Criteria:Hibernate核心接口
在 Hibernate 中,有六个常用的核心接口,它们分别是 Configuration、SessionFactory、Session、Transaction、Query 和 Criteria。在接下来的几个小节中,将对这六个核心接口进行详细讲解。
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 对象。下面就介绍一个简单的抽取方式,如下所示。
public class HibernateUtils { // 声明一个私有的静态final类型的Configuration对象 private static final Configuration config; // 声明一个私有的静态的final类型的SessionFactory对象 private static final SessionFactory factory; // 通过静态代码块构建SessionFactory static { config = new Configuration().configure(); factory = config.buildSessionFactory(); } // 提供一个公有的静态方法供外部获取,并返回一个session对象 public static Session getSession() { return factory.openSession(); } }
上述代码中,首先声明了一个私有的静态 final 类型的 Configuration 对象和 SessionFactory 对象,供类中的其他成员使用,下面通过静态方法构建了 SessionFactory 实例,最后提供了一个公有的静态方法供外部获取 session 对象。使用此工具类,就可以直接通过 HibernateUtils.getSession() 的方式获取 session 对象。
Session
Session 是 Java 应用程序和 Hibernate 进行交互时所使用的主要接口,是持久化操作的核心 API。它主要用于读取、创建和删除映射对象的实例,这一系列的操作将被转换为数据表中的增加、修改、查询和删除操作。
Session 是轻量级的,实例的创建和销毁不需要消耗太多的资源,同时它还是 Hibernate 的一级缓存,这个缓存主要用于存放当前工作单元加载的对象。
获取 Session 实例有两种方式,一种是通过 openSession() 方法,另一种是通过 getCurrentSession() 方法。两种方法获取 Session 的代码如下所示:
//采用openSession方法创建Session Session session = sessionFactory.openSession(); //采用getCurrentSession()方法创建Session Session session = sessionFactory.getCurrentSession();
以上两种获取 Session 实例的主要区别是:采用 openSession() 方法获取 Session 实例时,SessionFactory 直接创建一个新的 Session 实例,并且在使用完成后需要调用 close() 方法进行手动关闭;而 getCurrentSession() 方法创建的 Session 实例会被绑定到当前线程中,它在提交或回滚操作时会自动关闭。
在 Session 中,提供了多个持久化的操作方法,其常用方法如表 1 所示。
名称 | 描述 |
---|---|
save() | 用于执行添加对象操作 |
update() | 用于执行修改对象操作 |
saveOrUpdate() | 用于执行添加或修改对象操作 |
delete() | 用于执行删除对象操作 |
get() | 根据主键查询数据 |
load() | 根据主键查询数据 |
createQuery() | 用于数据库操作对象 |
createSQLQuery() | 用于数据库操作对象 |
createCriteria() | 面向对象的条件查询 |
需要注意的是,Session 是线程不安全的,当多个并发线程同时操作一个 Session 实例时,就可能导致 Session 数据存取的混乱(当方法内部定义和使用 Session 时,不会出现线程问题)。因此设计软件架构时,应避免多个线程共享一个 Session 实例。
Transaction
Transaction 接口主要是用于管理事务,它是 Hibernate 的数据库事务接口,且对底层的事务接口进行了封装。Transaction 接口的实例对象是通过 Session 对象开启的,其开启方式如下所示:
Transaction transaction = session.beginTransaction();
在 Transaction 接口中,提供了事务管理的常用方法,具体如下。
- commit() 方法:提交相关联的 session 实例。
- rollback() 方法:撤销事务操作。
- wasCommitted() 方法:检查事务是否提交。
当应用程序执行完持久化操作后,需要调用 commit() 方法提交事务,或者调用 rollback() 方法回滚事务(取消事务),可以通过以下代码加以理解:
try{ transaction = session.beginTransaction(); //开启事务 session.save(user); //执行操作 transaction.commit(); //提交事务 }catch(Exception e) { transaction.rollback(); //回滚事务 }finally{ session.close(); //关闭资源 }
从上述代码中可以看出,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 语句如下所示:
INSERT INTO `hibernate`.`user` (`id`, `name`, `age`, `gender`) VALUES (1, 'zhangsan', '21', '男') ; INSERT INTO `hibernate`.`user` (`id`, `name`, `age`, `gender`) VALUES (2, 'xiaozhang', '21', '男') ; INSERT INTO `hibernate`.`user` (`id`, `name`, `age`, `gender`) VALUES (3, 'lisisi', '22', '女') ; INSERT INTO `hibernate`.`user` (`id`, `name`, `age`, `gender`) VALUES (4, 'wangwu', '19', '男') ;
插入后,user 表中的数据如图 1 所示。
发表评论