Hibernate 使用教程:从入门到精通
Hibernate 是一个开源的 ORM(Object-Relational Mapping,对象关系映射)框架,它对 JDBC 进行了轻量级的对象封装,使得 Java 开发者可以使用面向对象的思想来操作数据库,而无需编写繁琐的 JDBC 和 SQL 代码。

目录
- 核心概念
- 什么是 ORM?
- Hibernate 的核心组件
- Hibernate 的工作原理
- 环境准备
- JDK
- IDE (IntelliJ IDEA / Eclipse)
- Maven
- 数据库
- 第一个 Hibernate 程序 (Hello World)
- 步骤 1: 创建 Maven 项目
- 步骤 2: 添加依赖
- 步骤 3: 创建实体类
- 步骤 4: 创建映射文件
- 步骤 5: 创建 Hibernate 配置文件
- 步骤 6: 编写测试代码
- 步骤 7: 运行与结果分析
- Hibernate 核心 API
ConfigurationServiceRegistryMetadataSessionFactorySessionTransactionQueryvsCriteria
- Hibernate CRUD 操作详解
- 保存
- 查询
- 更新
- 删除
- 进阶主题
- 关系映射 (一对一、一对多、多对多)
- HQL (Hibernate Query Language)
- 缓存机制
- 最佳实践与总结
核心概念
1 什么是 ORM?
ORM 是一种编程技术,用于将对象模型与关系型数据库的数据结构之间进行映射,通过 ORM,开发者可以用操作对象的方式(如 user.setName("张三"))来间接操作数据库,而 ORM 框架会自动将其转换为对应的 SQL 语句(如 UPDATE users SET name = '张三' WHERE id = 1)。
优点:
- 提高开发效率:无需编写大量重复的 JDBC 代码。
- 面向对象:代码更易于理解和维护。
- 数据库无关性:更换数据库时,只需修改少量配置,业务代码基本不变。
2 Hibernate 的核心组件
- Configuration:负责配置并启动 Hibernate,读取
hibernate.cfg.xml或persistence.xml文件。 - SessionFactory:线程安全的重量级对象,是生产
Session的工厂,它代表了数据库的连接池,一个数据库对应一个SessionFactory。 - Session:轻量级非线程安全的对象,相当于 JDBC 中的
Connection,它是应用程序与数据库交互的主要接口,用于执行 CRUD 操作。 - Transaction:管理事务,确保数据的一致性。
- Persistent Object (PO) / Entity Bean:与数据库表映射的 Java 对象。
- Mapping File:XML 文件(或注解),用于定义 PO 与数据库表之间的映射关系。
3 Hibernate 的工作原理
- 读取并解析配置文件 (
hibernate.cfg.xml) 和映射文件 (.hbm.xml或注解)。 - 创建
Configuration对象,并根据配置创建一个SessionFactory对象。 - 应用程序从
SessionFactory中获取一个Session对象。 - 开启一个事务 (
Transaction)。 - 通过
Session对象与数据库进行交互(CRUD)。 - 提交事务或回滚事务。
- 关闭
Session和SessionFactory。
环境准备
- JDK 8+
- IDE: IntelliJ IDEA 或 Eclipse
- Maven: 用于管理项目依赖
- 数据库: MySQL (本教程以 MySQL 为例)
第一个 Hibernate 程序
我们将创建一个简单的程序,向数据库中插入一条用户信息。
步骤 1: 创建 Maven 项目
在 IDE 中创建一个新的 Maven 项目,选择 maven-archetype-quickstart 模板。

步骤 2: 添加依赖
打开 pom.xml 文件,添加 Hibernate、MySQL 驱动和 JUnit 依赖。
<dependencies>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<!-- Hibernate Core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.14.Final</version>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
</dependencies>
注意:请确保你的 pom.xml 中有 <build> 配置,以包含 src/main/java 下的资源文件。
步骤 3: 创建实体类
在 src/main/java 下创建你的实体类,com.example.entity.User。
package com.example.entity;
import javax.persistence.*;
@Entity // 告诉 Hibernate 这是一个实体类,会映射到一张数据库表
@Table(name = "t_user") // 指定映射的表名
public class User {
@Id // 指定这是主键
@GeneratedValue(strategy = GenerationType.IDENTITY) // 指定主键生成策略,IDENTITY 表示自增
private Long id;
@Column(name = "username") // 指定映射的列名,如果不写则默认为属性名
private String username;
@Column(name = "password")
private String password;
// 无参构造器是必须的
public User() {
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
说明:这里我们使用了 JPA 注解来简化映射,这是目前的主流方式,你也可以选择使用 XML 映射文件(.hbm.xml),但注解更方便。

步骤 4: 创建映射文件
(如果使用注解,此步可省略,这里仅为说明)。
在 src/main/resources 下创建 User.hbm.xml 文件。
<?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 package="com.example.entity">
<class name="User" table="t_user">
<id name="id" column="id">
<generator class="identity"/>
</id>
<property name="username" column="username"/>
<property name="password" column="password"/>
</class>
</hibernate-mapping>
步骤 5: 创建 Hibernate 配置文件
在 src/main/resources 下创建 hibernate.cfg.xml 文件,这是 Hibernate 的核心配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 1. 数据库连接信息 -->
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_demo?useSSL=false&serverTimezone=UTC</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">your_password</property>
<!-- 2. Hibernate 相关配置 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 3. 映射文件引入 -->
<!-- 如果使用注解,这里不需要引入 .hbm.xml 文件 -->
<!-- <mapping resource="com/example/entity/User.hbm.xml"/> -->
<!-- 如果使用注解,需要扫描实体类所在的包 -->
<mapping class="com.example.entity.User"/>
</session-factory>
</hibernate-configuration>
配置项说明:
hibernate.connection.*: JDBC 连接信息。hibernate.dialect: 指定数据库方言,Hibernate 会针对不同数据库生成优化的 SQL。hibernate.show_sql: 在控制台打印生成的 SQL 语句,方便调试。hibernate.format_sql: 格式化输出的 SQL。hibernate.hbm2ddl.auto: 自动管理表结构。update: 如果表结构发生变化,会自动更新表(开发环境常用)。create: 每次启动都会创建新表,数据会丢失(测试环境偶尔使用)。create-drop: 启动时创建,关闭时删除。validate: 验证表结构,不创建也不更新(生产环境常用)。
步骤 6: 编写测试代码
在 src/test/java 下创建测试类 com.example.HibernateTest。
package com.example;
import com.example.entity.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.jupiter.api.Test;
public class HibernateTest {
@Test
public void testSaveUser() {
// 1. 加载 Hibernate 配置文件,创建 Configuration 对象
Configuration config = new Configuration().configure();
// 2. 创建 ServiceRegistry 对象 (Hibernate 5.x 之后推荐方式)
// ServiceRegistry registry = new StandardServiceRegistryBuilder()
// .applySettings(config.getProperties()).build();
// SessionFactory sessionFactory = config.buildSessionFactory(registry);
// 简化方式 (内部会自动处理 ServiceRegistry)
SessionFactory sessionFactory = config.buildSessionFactory();
// 3. 获取 Session 对象
Session session = sessionFactory.openSession();
// 4. 开启事务
Transaction transaction = session.beginTransaction();
try {
// 5. 执行保存操作
User user = new User();
user.setUsername("zhangsan");
user.setPassword("123456");
// 保存 user 对象到数据库
session.save(user);
// 6. 提交事务
transaction.commit();
System.out.println("保存成功!用户ID: " + user.getId());
} catch (Exception e) {
// 7. 发生异常,回滚事务
transaction.rollback();
e.printStackTrace();
} finally {
// 8. 关闭资源
session.close();
sessionFactory.close();
}
}
}
注意:SessionFactory 和 Session 的创建和关闭是比较耗时的操作,在实际项目中,SessionFactory 通常作为单例,而 Session 是非线程安全的,应在每个线程中创建和关闭。
步骤 7: 运行与结果分析
- 准备数据库:在 MySQL 中创建一个名为
hibernate_demo的数据库。CREATE DATABASE hibernate_demo;
- 运行测试:在 IDE 中运行
testSaveUser()方法。 - 查看结果:
- 控制台:你会看到 Hibernate 打印出的建表 SQL 和插入 SQL。
Hibernate: create table t_user ( id bigint not null auto_increment, password varchar(255), username varchar(255), primary key (id) ) engine=InnoDB Hibernate: insert into t_user (password, username) values (?, ?) 保存成功!用户ID: 1 - 数据库:查看
hibernate_demo数据库,会发现多了一张t_user表,并且其中有一条新记录。
- 控制台:你会看到 Hibernate 打印出的建表 SQL 和插入 SQL。
Hibernate 核心 API
Configuration:读取配置文件,创建SessionFactory。Configuration config = new Configuration().configure();
SessionFactory:重量级,线程安全,全局唯一,管理数据库连接池。SessionFactory sessionFactory = config.buildSessionFactory();
Session:轻量级,非线程安全,相当于 JDBC 的Connection,用于执行 CRUD。Session session = sessionFactory.openSession();
Transaction:管理事务。Transaction tx = session.beginTransaction(); tx.commit(); // 提交 // tx.rollback(); // 回滚
Query/Criteria:执行查询。Query:使用 HQL (Hibernate Query Language) 或原生 SQL。Criteria:使用面向对象的条件查询,更安全但较繁琐。
Hibernate CRUD 操作详解
1 保存
我们已经在上面的例子中演示了 session.save(user)。
2 查询
根据 ID 查询 (最常用)
@Test
public void testGetUserById() {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
try {
// 使用 get() 方法,立即加载,如果对象不存在,返回 null
User user = session.get(User.class, 1L); // 1L 是主键 ID
System.out.println("查找到的用户: " + user);
// 使用 load() 方法,延迟加载(返回一个代理对象),当真正使用对象属性时才发 SQL 查询
// 如果对象不存在,会抛出 ObjectNotFoundException
// User userProxy = session.load(User.class, 1L);
// System.out.println("代理对象的类: " + userProxy.getClass().getName()); // 会打印出代理类
// System.out.println("用户名: " + userProxy.getUsername()); // 此时才会真正执行 SQL
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
3 更新
更新操作通常分为两步:先查询,再修改,update。
@Test
public void testUpdateUser() {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
try {
// 1. 先查询出要更新的对象
User user = session.get(User.class, 1L);
// 2. 修改对象的属性
if (user != null) {
user.setPassword("new_password_123");
}
// 3. 调用 update 方法
// 注意:Hibernate 的脏检查机制,只要对象处于持久态(被 session 管理),修改后会自动同步到数据库,
// 显式调用 update 不是必须的,但可以确保更新。
session.update(user);
tx.commit();
System.out.println("更新成功!");
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
4 删除
删除操作也需要先查询出对象。
@Test
public void testDeleteUser() {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
try {
// 1. 先查询出要删除的对象
User user = session.get(User.class, 1L);
// 2. 调用 delete 方法
if (user != null) {
session.delete(user);
}
tx.commit();
System.out.println("删除成功!");
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
进阶主题
1 关系映射
关系映射是 ORM 的核心之一。
- 多对一:多个
Student(学生) 属于一个Grade(班级)。- 在
Student实体中添加Grade属性和@ManyToOne注解。
- 在
- 一对多:一个
Grade(班级) 包含多个Student(学生)。- 在
Grade实体中添加List<Student>属性和@OneToMany注解。
- 在
- 一对一:一个
Person(人) 对应一个IdCard(身份证)。- 使用
@OneToOne注解,通常通过主键或外键关联。
- 使用
- 多对多:一个
Student(学生) 可以选修多门Course(课程),一门Course也可以被多个Student选修。- 需要创建一个中间表(关联表)来维护关系。
- 在
Student中使用@ManyToMany注解关联Set<Course>。 - 在
Course中使用@ManyToMany注解关联Set<Student>。
2 HQL (Hibernate Query Language)
HQL 是 Hibernate 提供的一种面向对象的查询语言,语法类似于 SQL,但操作的是对象和属性而非表和列。
@Test
public void testHQL() {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
try {
// 1. 创建 Query 对象
// 查询所有 User
Query<User> query = session.createQuery("from User", User.class);
// 2. 执行查询,获取结果列表
List<User> userList = query.list();
userList.forEach(System.out::println);
System.out.println("--------------------");
// 带条件的查询 (使用参数占位符)
Query<User> query2 = session.createQuery("from User where username = :username", User.class);
query2.setParameter("username", "zhangsan");
User user = query2.uniqueResult(); // uniqueResult() 用于期望只有一个结果时
System.out.println("按用户名查询: " + user);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
3 缓存机制
Hibernate 提供了强大的缓存机制来提升性能。
-
一级缓存 (Session 级别):
- 特点:默认开启,生命周期与
Session相同,范围在Session内部。 - 作用:当同一个
Session中多次查询同一个对象时,只会发送一次 SQL,后续从缓存中获取。 - 管理:无需手动管理,
Session关闭时一级缓存销毁。
- 特点:默认开启,生命周期与
-
二级缓存 (SessionFactory 级别):
- 特点:默认关闭,生命周期与
SessionFactory相同,范围是全局的。 - 作用:可以被所有
Session共享,用于减轻数据库压力。 - 配置:需要额外配置(如引入
ehcache库,并在hibernate.cfg.xml和实体类上配置)。
- 特点:默认关闭,生命周期与
最佳实践与总结
- 使用注解:在现代 Java 开发中,使用 JPA 注解进行映射是绝对的主流,比 XML 映射文件更简洁、更易于维护。
SessionFactory管理:SessionFactory是重量级对象,应该在整个应用生命周期中只创建一次,通常使用单例模式或依赖注入(如 Spring 框架)来管理。Session管理:Session是轻量级且非线程安全的,不要在多个线程间共享它,最佳实践是“一次请求,一个Session”,在请求开始时打开,在请求结束时关闭。- 事务管理:确保所有数据库操作都在事务中完成,推荐使用声明式事务管理(如 Spring 的
@Transactional),而不是编程式事务。 - 合理使用 HQL:HQL 强大且灵活,但要注意 SQL 注入风险(使用参数绑定),对于简单的 CRUD,Hibernate 的
CriteriaAPI 或 JPA 的EntityManagerAPI 也是不错的选择。 - 了解缓存:合理利用一级和二级缓存可以显著提升应用性能,但要警惕缓存带来的数据一致性问题。
- 选择合适的主键生成策略:
IDENTITY(自增) 适合 MySQL,SEQUENCE适合 Oracle,UUID适合分布式系统。
Hibernate 是一个非常成熟的 ORM 框架,极大地简化了数据库操作,掌握其核心概念、配置和 API 是进行 Java 企业级开发的基础,随着 JPA 标准的普及,Hibernate 作为其最优秀的实现之一,依然是开发者不可或缺的工具。
