Hibernate核心接口(5个)

1年前 (2024-04-27)

在 Hibernate 中有 5 个常用的核心接口,它们分别是 Configuration 接口、SessionFactory 接口、Session 接口、Transaction 接口和 Query 接口。本节,我们就对这 5 个核心接口进行详细讲解。

1. Configuration

正如其名,Configuration 主要用于管理 Hibernate 配置信息,并在启动 Hibernate 应用时,创建 SessionFactory 实例。

在 Hibernate 应用启动时,需要获取一些基本信息,例如,数据库 URL、数据库用户名、数据库用户密码、数据库驱动程序和数据库方言等等。这些属性都可以在 Hibernate 的核心配置文件(hiberntae.cfg.xml)中进行设置。

创建 Configuration 实例

Hibernate 通常使用以下方式创建 Configuration 实例,此时  Hibernate 会自动在当前项目的类路径(CLASSPATH)中,搜索核心配置文件 hibernate.cfg.xml 并将其加载到内存中,作为后续操作的基础配置 。

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


若 Hibernate 核心配置文件没有在项目的类路径( src 目录)下,则需要在 configure() 方法中传入一个参数指定配置文件位置,示例代码如下:

Configuration configuration = new Configuration().configure("/net/biancheng/www/mapping/hibernate.cfg.xml");

加载映射文件

我们知道,在 Hibernate 的核心配置文件中,<mapping> 元素用来指定 Hibernate 映射文件的位置信息,加载映射文件,但该元素并非核心配置文件中的必须元素,即我们可以不在 hibernate.cfg.xml 中指定映射文件的位置。此时,我们可以通过 2 种方式加载映射文件。

1. 调用 Configuration 提供的 addResource() 方法,并在该方法中传入一个参数指定映射文件的位置,示例代码如下。

configuration.addResource("net/biancheng/www/mapping/User.hbm.xml");


2. 调用 Configuration 提供的 addClass() 方法,并将与映射文件对应的实体类以参数的形式传入该方法中,示例代码如下。

configuration.addClass(User.class);


使用 addClass() 方法加载映射文件时,需要同时满足以下 2 个条件,否则将无法加载映射文件。

  • 映射文件的名要规范,即映射文件要完全按照“实体类.hbm.xml ”的形式名;

  • 映射文件要与实体类在同一个包下。


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

2. SessionFactory

SessionFactory 对象用来读取和解析映射文件,并负责创建和管理 Session 对象。

SessionFactory 对象中保存了当前的数据库配置信息、所有映射关系以及 Hibernate 自动生成的预定义 SQL 语句,同时它还维护了 Hibernate 的二级缓存。

一个 SessionFactory 实例对应一个数据库存储源,Hibernate 应用可以从 SessionFactory 实例中获取 Session 实例。

SessionFactory 具有以下特点:

  • SessionFactory 是线程安全的,它的同一个实例可以被应用多个不同的线程共享。

  • SessionFactory 是重量级的,不能随意创建和销毁它的实例。如果应用只访问一个数据库,那么在应用初始化时就只需创建一个 SessionFactory 实例;如果应用需要同时访问多个数据库,那么则需要为每一个数据库创建一个单独的 SesssionFactory 实例。

SessionFactory 之所以是重量级的,是因为它需要一个很大的缓存,用来存放预定义 SQL 语句以及映射关系数据等内容。我们可以为 SessionFactory 配置一个缓存插件,它被称为 Hiernate 的二级缓存,此处了解即可,我们会在后面详细介绍。

创建 SessionFactory 对象

通常情况下,我们通过 Configuration 的 buildSessionFactory() 方法来创建 SessionFactory 的实例对象,示例代码如下。

SessionFactory sessionFactory = configuration.buildSessionFactory();

抽取工具类

由于 SessionFactory 是重量级的,它的实例不能随意创建和销毁,因此在实际开发时,我们通常会抽取出一个工具类,将 SessionFactory 对象的创建过程放在静态代码快中,以避免 SessionFactory 对象被多次创建。

例如,在 hibernate-demo 项目的 net.biancheng.www.utils 包下,创建一个工具类 HibernateUtils,代码如下。

package net.biancheng.www.utils;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

/**

* 工具类

*/

public class HibernateUtils {

private static final Configuration configuration;

private static final SessionFactory sessionFactory;

//在静态代码块中创建 SessionFactory 对象

static {

configuration = new Configuration().configure();

sessionFactory = configuration.buildSessionFactory();

}

//通过 SessionFactory 对象创建 Session 对象

public static Session openSession() {

return sessionFactory.openSession();

}

public static void main(String[] args) {

// openSession();

HibernateUtils hibernateUtils = new HibernateUtils();

}

}

由以上代码可知,我们直接调用 HibernateUtils 的 getSession() 的方式,便可以获取 Session 对象。

3. Session

Session 是 Hibernate 应用程序与数据库进行交互时,使用最广泛的接口,它也被称为 Hibernate 的持久化管理器,所有持久化对象必须在 Session 的管理下才可以进行持久化操作。持久化类只有与 Session 关联起来后,才具有了持久化的能力。

Session 具有以下特点:

  • 不是线程安全的,因此应该避免多个线程共享同一个 Session 实例;

  • Session 实例是轻量级的,它的创建和销毁不需要消耗太多的资源。通常我们会将每一个Session 实例和一个数据库事务绑定,每执行一个数据库事务,不论执行成功与否,都因该调用 Session 的 Close() 方法,关闭 Session 释放占用的资源。


Session 对象维护了 Hibernate 的一级缓存,在显式执行 flush 之前,所有的持久化操作的数据都缓存在 Session 对象中。

这里的持久化指的是对数据库数据的保存、更新、删除和查询。持久化类指与数据库表建立了映射关系的实体类,持久化对象指的是持久化类的对象。

关于持久化以及一级缓存的概念,这里了解即可,我们会在 Hibernate 持久化类和 Hibernate 一级缓存中详细讲解。

创建 Session 对象

我们可以通过以下 2 个方法创建 Session 对象:

1.调用 SessionFactrory 提供的 openSession() 方法,来获取 Session 对象,示例代码如下。

//采用 openSession() 方法获取 Session 对象

Session session = sessionFactory.openSession();


2. 调用SessionFactrory 提供的 getCurrentSession() 方法,获取 Session 对象,示例代码如下。

//采用 getCurrentSession() 方法获取 Session 对象

Session session = sessionFactory.getCurrentSession();


以上 2 种方式都能获取 Session 对象,但两者的区别在于:

  • 采用 openSession() 方法获取 Session 对象时,SessionFactory 直接创建一个新的 Session 实例,且在使用完成后需要调用 close() 方法进行手动关闭。

  • 采用 getCurrentSession() 方法创建的 Session 实例会被绑定到当前线程中,它在事务提交或回滚后会自动关闭。

Session 中的持久化方法

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

方法

描述

save()

执行插入操作

update()

执行修改操作

saveOrUpdate()

根据参数,执行插入或修改操作

delete()

执行删除操作

get()

根据主键查询数据(立即加载)

load()

根据主键查询数据(延迟加载)

createQuery()

获取 Hibernate 查询对象

createSQLQuery()

获取 SQL 查询对象

注意:Hibernate 中的 Session 与 Java Web 中的 HttpSession 没有任何关系,如无特别说明,本教程中的 Session 都指的是 Hibernate 中的 Session。

4. Transaction 

Transaction 是 Hibernate 提供的数据库事务管理接口,它对底层的事务接口进行了封装。所有的持久化操作(即使是只读操作)都应该在事务管理下进行,因此在进行 CRUD 持久化操作之前,必须获得 Trasaction 对象并开启事务。

获取 Transaction 对象

我们可以通过 Session 提供的以下两个方法来获取 Transaction 对象:

1. 调用 Session 提供的 beginTransaction() 方法获取 Transaction 对象,示例代码如下。

Transaction transaction = session.beginTransaction();


2. 调用 Session 提供的 getTransaction() 方法获取 Transaction 对象,示例代码如下。

Transaction transaction1 = session.getTransaction();


以上两个方法均可以获取 Transaction 对象,但两者存在以下不同:

  • getTransaction() 方法:根据 Session 获得一个 Transaction 对象,但是并没有开启事务。

  • beginTransaction() 方法:是在根据 Session 获得一个 Transaction 对象后,又继续调用 Transaction 的 begin() 方法,开启了事务。


Transation 接口中提供了管理事务的方法,常用方法如下表。

方法

描述

begin()

该方法用于开启事务

commit() 

该方法用于提交事务

rollback() 

该方法用于回滚事务

提交或回滚事务

持久化操作执行完成后,需要调用了 Transaction 接口的 commit() 方法进行事务提交,只有在事务提交后,才能真正地将数据同步到数据库中。当发生异常时,则需要调用 rollback() 方法进行事务回滚,以避免数据发生错误,示例代码如下。

@Test

public void test() {

User user = new User();

Session session = HibernateUtils.openSession();

//获取事务对象

Transaction transaction = session.getTransaction();

//开启事务

transaction.begin();

try {

//执行持久化操作

Serializable save = session.save(user);

//提交事务

transactio网站站点" rel="nofollow" />

@Test

public void testHqlInsert() {

//获取 Session 对象

Session session = HibernateUtils.openSession();

//获取事务对象

Transaction transaction = session.getTransaction();

//开启事务

transaction.begin();

//更新操作

Query query = session.createQuery("update User SET userName=:username,userId=:userId,email=:email where id=:id");

//为更新语句设置参数

query.setParameter("username", "HQL");

query.setParameter("userId", "HQL");

query.setParameter("email", "HQL");

query.setParameter("id", 4);

//执行更新操作

int i = query.executeUpdate();

if (i > 0) {

System.out.println("成功修改了 " + i + " 条记录");

}

//删除操作

Query query1 = session.createQuery("delete from User WHERE userId=?1");

//为删除语句设置参数

query1.setParameter(1, "005");

//执行删除操作

int d = query1.executeUpdate();

if (d > 0) {

System.out.println("成功删除了 " + d + " 条记录");

}

//提交事务

transactio网站站点" rel="nofollow" />

Hibernate:

update

user

set

user_name=?,

user_id=?,

email=?

where

id=?

成功修改了 1 条记录

Hibernate:

delete

from

user

where

user_id=?

成功删除了 1 条记录


查看数据库 user 表,结果如下。

HQL 更新删除结果

图1:HQL 更新删除结果

从上图可知,我们成功地使用 HQL 进行更新和删除操作。