Hibernate介绍
Hibernate是一个开源的Java对象关系映射(ORM)框架,它提供了一种方便的方式将Java对象与关系型数据库进行映射和交互。通过Hibernate,开发人员可以使用面向对象的方式操作数据库,而不需要直接编写SQL查询语句
架构图
Hibernate是一个开源的对象关系映射(ORM)框架,用于将Java对象映射到关系型数据库中的关系表。 它提供了一种面向对象的方式来操作数据库,简化了开发人员对数据库的访问和管理
如何理解提供了一种面向对象的方式来操作数据库。
一方面:Hibernate可以将定义好的java类映射为数据库中的表,并将java类的实例化的对象,映射为对应表中的一行记录。 另一方面:使用Hibernate,开发人员可以直接操作对象,不需要编写复杂的SQL语句。通过对象的属性和方法来进行数据的读取、修改和删除等操作。
Hibernate提供的核心功能和特性
ORM映射(可以将java对象与数据库表之间进行映射,实现对象和关系数据库之间的转换,支持各种映射策略和注解);
数据库查询(提供了一组丰富的API,用于执行数据库操作,包括插入、更新、删除、查询,还支持HQL和基于SQL的查询一级Criteria查询和原生SQL查询);
缓存机制(Hibernate内置了一级缓存和二级缓存机制,用于提供查询性能和减少数据库的访问。一级缓存是会话级别的缓存,保存了会话期间加载的实体对象。二级缓存是跨会话的缓存,可以在多个会话之间共享缓存数据);
事物管理(可以通过编程或声明式的方式管理数据库事物。支持标准的java事物API(JTA)和本地事物管理);
延迟加载(允许按需加载关联对象,提高查询性能。这意味着只有在需要访问关联对象时,才会从数据库中加载相应的数据。);
对象状态管理(通过跟踪对象的状态来管理对象的持久化。它提供了持久化、脱管和删除等状态之间的转换,使开发人员能够方便地操作对象。)
对象的持久化
把对象永久的保存到数据库中
持久化包括和数据库相关的各种操作
- 保存
- 更新
- 删除
- 查询
- 加载:加载特定的 OID,把一个对象从数据库加载到内存中
OID:为了在系统中能找到所需对象,需要为对象分配一个唯一的标识号,在关系型数据库中称为主键,在对象术语中叫对象标识OID
ORM 对象关系映射
ORM主要解决对象-关系的映射
- 类的一个对象可以对应一张表,对象对应表的行,属性对应位表的列
ORM的思想:将关系数据库中表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。 ORM 采用元数据来描述对象-关系映射细节,元数据通常采用XML 格式,并且存放在专门的对象-关系映射文件中。描述数据的数据

Hibernate框架的优点
使开发更加面向对象化:Hibernate提供了一个面向对象的编程模型,使开发人员可以使用面向对象的思想来操作数据库。
提高开发效率:Hibernate提供了许多强大的特性和工具:如自动生成数据库表结构,提供了公共的操作数据库的方法,让开发人员不用写SQL语句、缓存机制、事物管理。可以大大减少开发人员的工作量,提高开发效率。
可移植性:Hibernate可以在不同的数据库系统上运行,如Mysql、Oracle、SQL Server等,开发人员可以使用统一的API和语法,无需关系底层数据库的差异。
Hibernate、jpa、jdbc他们三者之间是什么关系
- jdbc:jdbc是Java提供的用于与关系型数据库进行交互的标准API,它提供了一组接口和类,使开发人员能够执行数据库的连接、查询、更新等操作。JDBC 需要开发人员手动编写 SQL 查询和处理数据库结果集,对于较低层次的数据库操作提供了灵活性。使开发人员能够执行数据库的连接、查询、更新等操作。JDBC 需要开发人员手动编写 SQL 查询和处理数据库结果集,对于较低层次的数据库操作提供了灵活性。
- JPA:JPA是Java持久化标准,定义了一组API和规范,提供了一种与数据库无关的方式来操作实体对象。JPA定义了实体、映射关系、查询语言和事物管理等方面的规范,使开发人员能够以面向对象的方式进行数据库的操作。
- Hibernate:Hibernate实现了JPA规范,同时还提供了一些额外的功能和特性。Hibernate封装了底层的JDBC操作,提供了更高层次的抽象,来简化开发人员对数据库的访问。通过 HIbernate 开发人员可以通过配置和注解来定义实体和映射关系,使用面向对象的方式进行数据库操作。
Hibernate 是 JPA 的实现之一,而 JPA 则是对数据库持久化操作的规范。JDBC 是底层的数据库连接和操作技术,Hibernate 和 JPA 则在 JDBC 的基础上提供了更高层次的抽象和便利性,使得开发人员能够以面向对象的方式进行数据库操作
下载安装
现在 Spring Boot JPA 集成的 Hibernate 进行数据持久化更加常见,
一般不用安装,装好依赖就行了,配置文件配置properties就行。
不用maven导入,jar包到 官网 下就行。
下载网站:https://sourceforge.net/projects/hibernate/files/hibernate-orm/
Hibernate开发步骤

第一个例子——学生信息管理
编写例子
创建了一个Java项目(Maven或Gradle)
添加了Hibernate依赖(如果是Maven项目,在pom.xml中添加)
1
2
3
4
5
6
7
8
9
10
11
12<!-- Hibernate核心依赖 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.14.Final</version>
</dependency>
<!-- 数据库驱动(这里使用H2内存数据库作为示例) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>创建实体类
使用hibernate时候,不需要自己手动创建表,hibernate帮把表创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75import javax.persistence.*;
public class Student {
// Hibernate作为JPA的实现,支持这些标准JPA注解
// 注解表示了对象关系映射的基本信息
// Hibernate 要求实体类有一个属性是唯一的
private Long id;
private String name;
private String email;
private Integer age;
// 必须有无参构造函数
public Student() {}
// 全参构造函数
public Student(String name, String email, Integer age) {
this.name = name;
this.email = email;
this.age = age;
}
// Getter和Setter方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}使用xml或者纯注解配置
Hibernate配置文件 hibernate.cfg.xml 是Hibernate框架中至关重要的部分,它负责初始化Hibernate并提供与数据库交互所需的所有配置信息。在这个配置文件中,开发者需要指定数据库连接的URL、用户名和密码,以及数据库使用的方言,这些信息是Hibernate能够正常工作所必须的。
该配置文件的结构通常包含以下几个主要部分:
- hibernate-configuration :这是配置文件的根元素,其中可以包含一个或多个 session-factory 元素。
- session-factory :定义了一个或多个 session-factory ,每一个 session-factory 都可以配置不同的数据库连接信息。
- property :在 session-factory 内部,使用多个 property 元素来指定Hibernate连接数据库所需的参数,如
- connection.url 、 connection.username 、 connection.password 、 dialect 等。
- mapping :这个元素用于指定实体类与数据库表的映射关系,可以通过 class 或 mapping-file 指定。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<hibernate-configuration>
<session-factory>
<!-- 数据库连接设置 -->
<property name="hibernate.connection.driver_class">org.h2.Driver</property>
<property name="hibernate.connection.url">jdbc:h2:mem:testdb</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<!-- JDBC连接池大小 -->
<property name="hibernate.connection.pool_size">1</property>
<!-- SQL方言 - 告诉Hibernate使用哪种数据库语法 -->
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<!-- 在控制台显示SQL语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 自动创建/更新数据库表结构 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 映射实体类 -->
<mapping class="com.example.Student"/>
</session-factory>
</hibernate-configuration>数据库连接和方言配置: 配置数据库连接信息是通过 hibernate.cfg.xml 中 property 元素的几个关键属性来完成的。 connection.url 指定了数据库的连接字符串, connection.username 和 connection.password 分别指定了数据库的用户名和密码,而 dialect 属性则指定了对应数据库的方言。 方言配置对于Hibernate的SQL生成至关重要。方言是Hibernate为不同数据库提供的抽象,它知道如何生成特定数据库支持的SQL语法。这样,Hibernate可以为不同的数据库产生正确的SQL语句而无需修改代码。
参数说明 :
connection.url :该属性定义了数据库的连接URL,格式取决于所使用的JDBC驱动程序。 connection.username 和 connection.password :分别定义了访问数据库时所需的用户名和密码。 dialect :该属性指定了数据库方言的完全限定类名,Hibernate根据这个类来生成特定数据库的SQL语句。
使用properties配置文件和xml配置属于是一样的
在纯注解方式下,我们可以完全摆脱
hibernate.cfg.xml
文件,使用Java配置类和JPA注解来配置Hibernate。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateUtil {
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
try {
Configuration configuration = new Configuration();
// 设置数据库连接属性
Properties settings = new Properties();
settings.put(AvailableSettings.DRIVER, "org.h2.Driver");
settings.put(AvailableSettings.URL, "jdbc:h2:mem:testdb");
settings.put(AvailableSettings.USER, "sa");
settings.put(AvailableSettings.PASS, "");
// Hibernate特定属性
settings.put(AvailableSettings.DIALECT, "org.hibernate.dialect.H2Dialect");
settings.put(AvailableSettings.SHOW_SQL, "true");
settings.put(AvailableSettings.HBM2DDL_AUTO, "update");
configuration.setProperties(settings);
// 添加实体类
configuration.addAnnotatedClass(Student.class);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
e.printStackTrace();
}
}
return sessionFactory;
}
public static void shutdown() {
if (sessionFactory != null) {
sessionFactory.close();
}
}
}创建主程序进行 CURD 操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73,创建SessionFactory对象import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import java.util.List;
public class HibernateDemo {
public static void main(String[] args) {
// 1. 创建SessionFactory,对应hibernate基本配置信息
// 加载hibernate核心配置文件,Configuration类加载 hibernate.cfg.xml
SessionFactory sessionFactory = new Configuration()
.configure("hibernate.cfg.xml")
.buildSessionFactory();
try {
// 2. 创建Session,创建SessionFactory对象
// 并且使用SessionFactory创建session对象,类似于连接
Session session = sessionFactory.openSession();
// 3. 开始事务
Transaction transaction = session.beginTransaction();
// 4. 创建学生对象并保存
Student student1 = new Student("张三", "zhangsan@example.com", 20);
Student student2 = new Student("李四", "lisi@example.com", 22);
System.out.println("保存学生...");
// 调用session的方法实现添加
session.save(student1);
session.save(student2);
// 5. 提交事务
transaction.commit();
// 6. 查询所有学生
transaction = session.beginTransaction();
System.out.println("\n查询所有学生...");
List<Student> students = session.createQuery("from Student", Student.class).list();
students.forEach(System.out::println);
// 7. 更新学生信息
System.out.println("\n更新学生信息...");
Student studentToUpdate = session.get(Student.class, student1.getId());
studentToUpdate.setEmail("newemail@example.com");
session.update(studentToUpdate);
// 8. 再次查询验证更新
System.out.println("\n查询更新后的学生...");
Student updatedStudent = session.get(Student.class, student1.getId());
System.out.println(updatedStudent);
// 9. 删除学生
System.out.println("\n删除学生...");
session.delete(student2);
// 10. 最终查询
System.out.println("\n最终学生列表...");
students = session.createQuery("from Student", Student.class).list();
students.forEach(System.out::println);
transaction.commit();
// 11. 关闭Session
session.close();
} finally {
// 12. 关闭SessionFactory
sessionFactory.close();
}
}
}这个例子使用了H2内存数据库,所以不需要额外安装数据库服务器,H2数据库非常适合学习和测试。
这个简单的示例展示了Hibernate的核心功能:
- 对象-关系映射:通过注解将Java类映射到数据库表
- CRUD操作:
- 创建(Create):
session.save()
- 读取(Read):
session.get()
和HQL查询 - 更新(Update):
session.update()
- 删除(Delete):
session.delete()
- 创建(Create):
- 事务管理:通过
Transaction
对象管理 - HQL查询:使用面向对象的查询语言
from Student
使用新的配置方式,该如何写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39import org.hibernate.Session;
import org.hibernate.Transaction;
public class HibernateAnnotationDemo {
public static void main(String[] args) {
// 获取SessionFactory
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
try {
// 开始事务
Transaction transaction = session.beginTransaction();
// 创建并保存学生
Student student1 = new Student("王五", "wangwu@example.com", 21);
Student student2 = new Student("赵六", "zhaoliu@example.com", 23);
System.out.println("保存学生...");
session.save(student1);
session.save(student2);
// 提交事务
transaction.commit();
// 查询示例
transaction = session.beginTransaction();
System.out.println("\n所有学生:");
List<Student> students = session.createQuery("from Student", Student.class).list();
students.forEach(System.out::println);
transaction.commit();
} finally {
session.close();
HibernateUtil.shutdown();
}
}
}其中的注解声明
注解 来源 说明 @Entity
JPA 标记类为实体类,将映射到数据库表 @Table
JPA 指定映射的表名 @Id
JPA 标记主键字段 @GeneratedValue
JPA 指定主键生成策略 @Column
JPA 指定字段与列的映射关系 @Transient
JPA 标记不持久化的字段
涉及到的API
Configuration
在使用Hibernate时,首先要创建Configuration实例,Configuration实例主要用于启动、加载、管理hibernate的配置文件信息。
- Hibernate 运行的底层信息:数据库的 URL,用户名,密码,JDBC驱动类,数据库Diaiect,数据库连接池等,对应hibernate.cfg.xml 文件
- 持久化类与数据表的映射关系 hbm.xml文件
在启动Hibernate的过程中,Configuration实例首先确定Hibernate配置文件的位置,然后读取相关配置,最后创建一个唯一的SessionFactory实例。Configuration对象只存在于系统的初始化阶段,它将SessionFactory创建完成后,就完成了自己的使命。
Hibernate通常使用Configuration config = new Configuration().configure();
的方式创建实例,此种方式默认会去src下读取hibernate.cfg.xml配置文件。如果不想使用默认的hibernate.cfg.xml
配置文件,而是使用指定目录下(或自定义)的配置文件,则需要向configure()
方法中传递一个文件路径的参数,其代码写法如下:
1 | Configuration config = new Configuration().configure("xml文件位置"); |
传递 hibernate.properties 属性文件
1 | Configuration config = new Configuration(); |
此种写法hibernate会去指定位置查找配置文件,例如,想要使用src下config包中的hibernate.cfg.xml文件,只需将文件位置加入configure()中即可,其代码如下所示:
1 | Configuration config = new Configuration().configure("/config/hibernate.cfg.xml"); |
SessionFactory
SessionFactory
接口负责Hibernate的初始化和建立Session对象。它在Hibernate中起到一个缓冲区作用,Hibernate可以将自动生成的SQL语句、映射数据以及某些可重复利用的数据放在这个缓冲区中。同时它还保存了对数据库配置的所有映射关系,维护了当前的二级缓存。
- 针对单个数据库映射关系经过编译后的内存镜像,是线程安全的。
- SessionFactory对象一且构造完毕,即被赋予特定的配置信息。
- SessionFactory是生成Session的工厂
- 构造SessionFactory很消耗资源,一般情况下一个应用中只初始化一个SessionFactory对象。
- Hibernate4 新增了一个ServiceRegistry接口,所有基于Hibernate 的配置或者服务都必须统一向这个ServiceRegistry注册后才能效,但是 Hibernate5 又不需要了
SessionFactory实例是通过Configuration对象获取的,其获取方法如下所示:
1 | SessionFactory sessionFactory = config.buildSessionFactory(); |
SessionFactory具有以下特点:
- 它是线程安全的,它的同一个实例能够供多个线程共享。
- 它是重量级的,不能随意的创建和销毁它的实例。
由于SessionFactory
的这些特点,一般情况下,一个项目中只需要一个SessionFactory
,只有当应用中存在多个数据源时,才为每个数据源建立一个SessionFactory
实例。因此,在实际项目使用中,通常会抽取出一个HibernateUtils
的工具类,用来提供Session
对象。
Session
Session是应用程序与数据库之间交互操作的一个单线程对象,是Hibernate运作的中心,它的主要功能是为持久化对象提供创建、读取和删除的能力,所有持久化对象必须在session的管理下才可以进行持久化操作。
相当于 JDBC 的 Connection,持久化类与 Session 关联起来之后就具有了持久化的能力
创建SessionFactory实例后,就可以通过它获取Session实例。获取Session实例有两种方式,一种是通过openSession()
方法,另一种是通过getCurrentSession()
方法。两种方法获取session
的代码如下:
1 | // 采用openSession方法创建session => 获得全新session |
以上两种获取session实例方式的主要区别是,采用openSession方法获取Session实例时,SessionFactory直接创建一个新的Session实例,并且在使用完成后需要调用close方法进行手动关闭。而getCurrentSession方法创建的Session实例会被绑定到当前线程中,它在提交或回滚操作时会自动关闭。
Session是线程不安全的,多个并发线程同时操作一个Session实例时,就可能导致Session数据存在混乱(方法内部定义和使用Session时,不会出现线程问题)。因此设计软件架构时,应避免多个线程共享一个Sesion实例。同时它也是轻量级的,实例的创建和销毁不需要消耗太多的资源。它还有一个缓存,即Hibernate的一级缓存,这个缓存主要用于存放当前工作单元加载的对象。
在Session中提供了大量的常用方法,具体如下:
save()
、update()
和saveOrUpdate()
方法:用于增加和修改对象delete()
方法:用于删除对象get()
和load()
方法:根据主键查询createQuery()
和createSQLQuery()
方法:用于数据库操作对象createCriteria()
方法:条件查询
Transaction
Transaction接口主要用于管理事务,它是Hibernate的数据库事务接口,且对底层的事务接口进行了封装。Transaction接口的事务对象是通过Session对象开启的,其开启方式如下所示:
1 | Transaction transaction = session.beginTransaction(); |
在Transaction接口中,提供了事务管理的常用方法,具体如下:
commit()
方法:提交相关联的session实例。rollback()
方法:撤销事务操作wasCommitted()
方法:检查事务是否提交
**Session执行完数据库操作后,要使用Transaction
接口的commit()
方法进行事务提交,才能真正的将数据操作同步到数据库中。
发生异常时,需要使用rollback()
方法进行事务回滚,以避免数据发送错误。因此,在持久化操作后,必须调用Transaction
接口的commit()
方法和rollback()
方法。如果没有开启事务,那么每个Session
的操作,都相当于一个独立的操作。