在 Hibernate操作数据库一节的学习中,我们主要涉及到了 Configuration、SessionFactory、Session、Transaction 和 Query 等多个接口,这些接口在 Hibernate 运行时都扮演着十分重要的角色,本节我们就来介绍以一下 Hibernate 运行时的工作原理。
关于 Configuration、SessionFactory、Session、Transaction 和 Query 等接口的使用,我们会在 Hibernate 的核心接口一节中进行详细的讲解,
Hibernate 运行时的执行流程如下图。
由上图可知,Hibernate 工作流程一般分为如下 7 步:
- Hibernate 启动,Configruation 会读取并加载 Hibernate 核心配置文件和映射文件钟的信息到它实例对象中。
- 通过 Configuration 对象读取到的配置文件信息,创建一个 SessionFactory 对象,该对象中保存了当前数据库的配置信息、映射关系等信息。
- 通过 SessionFactory 对象创建一个 Session 实例,建立数据库连接。Session 主要负责执行持久化对象的增、删、改、查操作,创建一个 Session 就相当于创建一个新的数据库连接。
- 通过 Session 对象创建 Transaction(事务)实例对象,并开启事务。Transaction 用于事务管理,一个 Transaction 对象对应的事务可以包含多个操作。需要注意的是,Hibernate 的事务默认是关闭的,需要手动开启和关闭。
- Session 接口提供了各种方法,可以对实体类对象进行持久化操作(即对数据库进行操作),例如 get()、load()、save()、update()、saveOrUpdate() 等等,除此之外,Session 对象还可以创建Query 对象 或 NativeQuery 对象,分别使用 HQL 语句或原生 SQL 语句对数据库进行操作。
- 对实体对象持久化操作完成后,必须提交事务,若程序运行过程中遇到异常,则回滚事务。
- 关闭 Session 与 SessionFactory,断开与数据库的连接,释放资源。
hibernate.cfg.xml(Hibernate核心配置文件)
Hibernate 的常用配置文件主要分为 2 种:核心配置文件(hibernate.cfg.xml)和映射文件(Xxx.hbm.xml),它们主要用于配置数据库连接、事务管理、Hibernate 本身的配置信息以及 Hibernate 映射文件信息。
本节我们只讲解 Hibernate 核心配置文件,也即 hibernate.cfg.xml,后续将在《Hibernate 映射文件》一节中继续讲解 Hibernate 映射文件。
hibernate.cfg.xml 被称为 Hibernate 的核心配置文件,它包含了数据库连接的相关信息以及映射文件的基本信息。通常情况下,该配置文件默认放在项目的 src 目录下,当项目发布后,该文件会在项目的 WEB-INF/classes 路径下。
hibernate.cfg.xml 中通常可以进行以下配置,这些配置中有些是必需配置,有些则是可选配置。
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--使用 Hibernate 自带的连接池配置-->
<property name="connection.url">jdbc:mysql://localhost:3306/bianchengbang_jdbc</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!--hibernate 方言-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!--打印sql语句-->
<property name="hibernate.show_sql">true</property>
<!--格式化sql-->
<property name="hibernate.format_sql">true</property>
<!-- 加载映射文件 -->
<mapping resource="net/biancheng/www/mapping/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
我们知道,在 XML 配置文件中 dtd 信息十分重要,它规定了 XML 中的语法和格式。Hibernate 核心配置的 dtd 信息,可以在 Hibernate 核心 Jar 包(hibernate-core-xxx.jar)下的 org.hibernate.hibernate-configuration-3.0.dtd 中找到,初学者只需要复制并使用该 dtd 信息即可。
Hibernate 核心配置文件的根元素是 <hibernate-configuration>,该元素中包含一个 <session-factory> 子元素。
<property> 元素
在 <session-factory> 元素中,包含了多个 <property> 子元素,这些元素用于配置 Hibernate 连接数据库的各种信息,例如,数据库的方言、驱动、URL、用户名、密码等。这些 property 属性中,有些是 Hibernate 的必需配置,有些则是可选配置,如下表。
property 属性名 |
描述 |
是否为必需属性 |
connection.url |
指定连接数据库 URL |
是 |
hibernate.connection.username |
指定数据库用户名 |
是 |
hibernate.connection.password |
指定数据库密码 |
是 |
connection.driver_class |
指定数据库驱动程序 |
是 |
hibernate.dialect |
指定数据库使用的 SQL 方言,用于确定 Hibernate 自动生成的 SQL 语句的类型 |
是 |
hibernate.show_sql |
用于设置是否在控制台输出 SQL 语句 |
否 |
hibernate.format_sql |
用于设置是否格式化控制台输出的 SQL 语句 |
否 |
hibernate.hbm2ddl.auto |
当创建 SessionFactory 时,是否根据映射文件自动验证表结构或自动创建、自动更新数据库表结构。 该参数的取值为 validate 、update、create 和 create-drop |
否 |
hibernate.connection.autocommit |
事务是否自动提交 |
否 |
Hibernate 能够访问多种关系型数据库,例如 MySQL、Oracle 等等,尽管多数关系型数据库都支持标准的 SQL 语言,但它们往往都还存在一些它们各自的独特的 SQL 方言,就像在不同地区的人既会说普通话,还能说他们各自的方言一样。hibernate.dialect 用于指定被访问的数据库的 SQL 方言,当 Hibernate 自动生成 SQL 语句或者使用 native 策略成主键时,都会参看该属性设置的方言。
<mapping> 元素
在 <session-factory> 元素中,除了 property 元素外,还可以包含一个或多个 <mapping> 元素,它们用来指定 Hibernate 映射文件的信息,加载映射文件。
- <mapping resource="net/biancheng/www/mapping/User.hbm.xml"/>
通常情况下,Hibernate 项目中存在多少映射文件,在核心配置文件中就配置多少个 <mapping> 元素。
Hibernate映射文件(Xxx.hbm.xml)
Hibernate 的常用配置文件主要分为 2 种:核心配置文件(hibernate.cfg.xml)和映射文件(Xxx.hbm.xml),它们主要用于配置数据库连接、事务管理、Hibernate 本身的配置信息以及 Hibernate 映射文件信息。
上节《hibernate.cfg.xml》中讲解了 Hibernate 核心配置文件,本节我们继续讲解 Hibernate 映射文件。
Hibernate 映射文件用于在实体类对象与数据表之间建立映射关系,每个映射文件的结构基本相同,示例代码如下所示。
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping schema="bianchengbang_jdbc">
<!-- name:类的全路径:-->
<!-- table:表的名称:(可以省略的.使用类的名称作为表名.)-->
<class name="net.biancheng.www.po.User" table="user">
<!--主键-->
<id name="id" column="id">
<!--主键生成策略-->
<generator class="native"></generator>
</id>
<property name="userId" column="user_id" type="java.lang.String"/>
<property name="userName" column="user_name"/>
<property name="password" column="password"/>
<property name="email" column="email"/>
</class>
</hibernate-mapping>
Hibernate 映射文件的 dtd 信息可以在 Hibernate 的核心 Jar 包(hibernate-core-xxx.jar)下的 org.hibernate.hibernate-mapping-3.0.dtd 文件中找到,初学者只需要复制并使用即可。
<hibernate-mapping> 元素
<hibernate-mapping> 是 Hibernate 映射文件的根元素,在该元素中定义的配置在整个映射文件中都有效。
<hibernate-mapping> 元素中常用的属性配置及其功能描述如下表。
属性名 |
描述 |
是否必需 |
schema |
指定映射文件所对应的数据库名字空间 |
否 |
package |
为映射文件对应的实体类指定包名 |
否 |
catalog |
指定映射文件所对应的数据库目录 |
否 |
default-access |
指定 Hibernate 用于访问属性时所使用的策略,默认为 property。当 default-access="property" 时,使用 getter 和 setter 方法访问成员变量;当 default-access = "field"时,使用反射访问成员变量。 |
否 |
default-cascade |
指定默认的级联风格 |
否 |
default-lazy |
指定 Hibernate 默认使用的延迟加载策略 |
否 |
<class> 元素
<class> 元素是 Hibernate 映射文件的根元素 <hibernate-mapping> 的子元素,它主要用来定义一个实体类与数据库表之间的映射关系,该元素中包含的常用属性如下表。
属性名 |
描述 |
是否必需 |
name |
实体类的完全限定名(包名+类名),若根元素 <hibernate-mapping> 中已经指定了 package 属性,则该属性可以省略包名 |
否 |
table |
对应的数据库表名。 |
否 |
catalog |
指定映射文件所对应的数据库 catalog 名称,若根元素 <hibernate-mapping> 中已经指定 catalog 属性,则该属性会覆盖根元素中的配置。 |
否 |
schema |
指定映射文件所对应的数据库 schema 名称,若根元素 <hibernate-mapping> 中已经指定 schema 属性,则该属性会覆盖根元素中的配置。 |
否 |
lazy |
指定是否使用延迟加载。 |
否 |
<id> 元素
通常情况下,Hibernate 推荐我们在持久化类(实体类)中定义一个标识属性,用于唯一地标识一个持久化实例(实体类对象),且标识属性需要映射到底层数据库的主键上。
在 Hibernate 映射文件中,标识属性通过 <id> 元素来指定,它是 <class> 元素的子元素,该元素中包含的常用属性如下表。
属性名 |
描述 |
是否必需 |
name |
与数据库表主键向对应的实体类的属性 |
否 |
column |
数据库表主键的字段名 |
否 |
type |
用于指定数据表中的字段需要转化的类型,这个类型既可以是 Hibernate 类型,也可以是 Java 类型 |
否 |
<id> 元素中通常还包含一个 <generator> 元素,该元素通过 class 属性来指定 Hibernate 的主键生成策略。
<id name="id" column="id" type="integer">
<!--主键生成策略-->
<generator class="native" ></generator>
</id>
Hibernate 提供了以下 7 主键生成策略,如下表。
主键生成策略 |
说明 |
increment |
自动增长策略之一,适合 short、int、long 等类型的字段。该策略不是使用数据库的自动增长机制,而是使用 Hibernate 框架提供的自动增长方式,即先从表中查询主键的最大值, 然后在最大值的基础上+1。该策略存在多线程问题,一般不建议使用。 |
identity |
自动增长策略之一,适合 short、int、long 等类型的字段。该策略采用数据库的自动增长机制,但该策略不适用于 Oracle 数据库。 |
sequence |
序列,适合 short、int、long 等类型的字段。该策略应用在支持序列的数据库,例如 Oracle 数据库,但不是适用于 MySQL 数据库。 |
uuid |
适用于字符串类型的主键,采用随机的字符串作为主键。 |
native |
本地策略,Hibernate 会根据底层数据库不同,自动选择适用 identity 还是 sequence 策略,该策略也是最常用的主键生成策略。 |
assigned |
Hibernate 框架放弃对主键的维护,主键由程序自动生成。 |
foreign |
主键来自于其他数据库表(应用在多表一对一的关系)。 |
<property> 元素
<class> 元素中可以包含一个或多个 <property> 子元素,它用于表示实体类的普通属性(除与数据表主键字段对应的属性之外的其他属性)和数据表中非主键字段的映射关系。该元素中包含的常用属性如下表。
属性名 |
描述 |
name |
实体类属性的名称 |
column |
数据表字段名 |
type |
用于指定数据表中的字段需要转化的类型,这个类型既可以是 Hibernate 类型,也可以是 Java 类型 |
length |
数据表字段的长度 |
lazy |
该属性使用延迟加载,默认值是 false |
unique |
是否对该字段使用唯一性约束。 |
not-null |
是否允许该字段为空 |
此外,在 Hibernate 映射文件中,父元素中子元素必须遵循一定的配置顺序,例如在 <class> 元素中必须先定义 <id>元素,再定义 <property> 元素,否则 Hibernate 的 XML 解析器在运行时会报错。