Hibernate ORM 入门:对象关系映射

FreeGuideOnline 最新 2026-06-17

Hibernate ORM 入门:对象关系映射

什么是 Hibernate ORM

Hibernate 是一个开源的 Java 持久层框架,它实现了 对象关系映射(Object-Relational Mapping,简称 ORM)。简单来说,ORM 通过将 Java 对象与数据库表进行映射,让我们可以用面向对象的方式操作数据库,而不必直接编写繁杂的 JDBC 和 SQL 语句。

借助 Hibernate,开发者可以将更多的注意力放在业务逻辑上,大幅减少数据持久层的代码量,同时还能获得数据库无关性、缓存、懒加载等高级特性。

环境准备与项目搭建

在开始之前,请确保你已经安装了 JDK 17+ 和一个 Java 集成开发环境(如 IntelliJ IDEA、Eclipse)。本文以 Maven 项目为例,使用 Hibernate 6.x 和 H2 内存数据库进行演示。

1. 创建 Maven 项目

在 IDE 中新建一个 Maven 项目,或者使用命令行:

mvn archetype:generate -DgroupId=com.example -DartifactId=hibernate-tutorial -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

2. 添加依赖

pom.xml 中加入以下依赖:

<dependencies>
    <!-- Hibernate ORM 核心 -->
    <dependency>
        <groupId>org.hibernate.orm</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>6.4.0.Final</version>
    </dependency>
    <!-- H2 数据库驱动(用于测试) -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>2.2.224</version>
    </dependency>
    <!-- 可选:日志框架 -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.4.12</version>
    </dependency>
</dependencies>

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>
        <!-- 数据库连接配置 -->
        <property name="hibernate.connection.driver_class">org.h2.Driver</property>
        <property name="hibernate.connection.url">jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1</property>
        <property name="hibernate.connection.username">sa</property>
        <property name="hibernate.connection.password"></property>

        <!-- 数据库方言,Hibernate 会自动生成适配的 SQL -->
        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>

        <!-- 自动建表策略:create-drop 会在启动时建表、关闭时删除 -->
        <property name="hibernate.hbm2ddl.auto">create-drop</property>

        <!-- 打印 SQL 语句,便于调试 -->
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>

        <!-- 指定要扫描的实体类 -->
        <mapping class="com.example.model.User"/>
    </session-factory>
</hibernate-configuration>

hibernate.hbm2ddl.auto 的常用值

  • create:每次启动都新建表,会丢失原有数据。
  • update:表不存在则创建,存在则更新结构(不会删除数据)。
  • create-drop:启动时创建表,SessionFactory 关闭时删除表。
  • validate:仅验证实体与数据库结构是否匹配,不会修改。

编写第一个实体类

com.example.model 包下新建 User 类,使用 JPA 注解进行映射。

package com.example.model;

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "username", nullable = false, unique = true, length = 50)
    private String username;

    @Column(name = "email")
    private String email;

    // 无参构造器是必需的
    public User() {}

    public User(String username, String email) {
        this.username = username;
        this.email = email;
    }

    // getter 和 setter 省略,实际开发中请补全
    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 getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    @Override
    public String toString() {
        return "User{id=" + id + ", username='" + username + '\'' + ", email='" + email + '\'' + '}';
    }
}

常用 JPA 注解说明

  • @Entity:声明该类为实体,会被 Hibernate 管理。
  • @Table:指定对应的数据库表名,默认使用类名小写。
  • @Id:主键字段。
  • @GeneratedValue:主键生成策略,IDENTITY 表示由数据库自增。
  • @Column:配置列属性,如非空、唯一、长度等。

创建 SessionFactory 和 Session

Hibernate 的持久化操作围绕 SessionFactorySession 展开。SessionFactory 是线程安全的重量级对象,通常在应用启动时创建一次;Session 是轻量级的,代表一次工作单元,使用后需要关闭。

新建一个 HibernateUtil 工具类:

package com.example.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.example.model.User;

public class HibernateUtil {
    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            return new Configuration()
                    .configure("hibernate.cfg.xml")
                    .addAnnotatedClass(User.class)
                    .buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        getSessionFactory().close();
    }
}

基本 CRUD 操作

现在我们来演示如何使用 Hibernate 进行增删改查。

1. 插入数据(CREATE)

Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;

try {
    tx = session.beginTransaction();
    User user = new User("john_doe", "john@example.com");
    session.persist(user);  // 等同于 JPA 的 persist,保证瞬时对象变为持久化
    tx.commit();
} catch (Exception e) {
    if (tx != null) tx.rollback();
    e.printStackTrace();
} finally {
    session.close();
}

2. 查询数据(READ)

Session session = HibernateUtil.getSessionFactory().openSession();
// 根据主键查询
User user = session.get(User.class, 1L);
System.out.println(user);

// 使用 HQL 查询所有用户
List<User> users = session.createQuery("FROM User", User.class).list();
users.forEach(System.out::println);
session.close();

3. 更新数据(UPDATE)

Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();

User user = session.get(User.class, 1L);
user.setEmail("newemail@example.com");
// 不需要显式调用 update,Hibernate 会自动检测脏数据并更新
tx.commit();
session.close();

4. 删除数据(DELETE)

Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();

User user = session.get(User.class, 1L);
session.remove(user);  // 或 session.delete(user)(旧版 API)
tx.commit();
session.close();

HQL 快速入门

HQL(Hibernate Query Language)是一种面向对象的查询语言,语法类似 SQL,但操作的是对象而非表。

常见 HQL 示例:

// 带参数的查询
Query<User> query = session.createQuery("FROM User WHERE username = :uname", User.class);
query.setParameter("uname", "john_doe");
User singleUser = query.uniqueResult();

// 模糊查询
List<User> list = session.createQuery("FROM User WHERE email LIKE :email", User.class)
        .setParameter("email", "%@example.com")
        .list();

// 使用原生 SQL
NativeQuery<User> nativeQuery = session.createNativeQuery("SELECT * FROM users", User.class);
List<User> allUsers = nativeQuery.list();

事务管理

Hibernate 中所有写操作(增、删、改)都必须在事务中执行,即使只是简单的更新。示例中我们都手动开始了事务:session.beginTransaction()

在实际项目中,推荐使用 Spring 的声明式事务管理,此处不做展开。但请牢记:没有事务的写操作会导致异常或数据不一致。

实体关系映射(基础)

为了完整理解 ORM,可以了解一下简单的关系映射。

一对多关系示例

假设一个用户有多篇文章。

@Entity
public class Article {
    @Id @GeneratedValue
    private Long id;
    private String title;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User author;
    // getter/setter...
}

在 User 类中添加:

@OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Article> articles = new ArrayList<>();

这样可以通过 user.getArticles() 获取该用户的所有文章,并能级联操作。

常见问题与最佳实践

  1. 懒加载异常(LazyInitializationException)
    在 Session 关闭后访问未初始化的代理对象时会触发。解决方案:在事务内完成数据获取,或使用 JOIN FETCH 查询。

  2. 一级缓存与二级缓存
    Hibernate 自带一级缓存(Session 缓存),同一个 Session 内重复查询不会产生多条 SQL。二级缓存需要额外配置(如 Ehcache),适合读多写少的场景。

  3. 避免手动 DDL
    充分利用 hibernate.hbm2ddl.auto = update 快速迭代开发,但生产环境建议使用数据库迁移工具(如 Flyway、Liquibase)。

  4. 始终管理 Session 生命周期
    使用 try-with-resources 或 finally 关闭 Session,防止连接泄漏。

  5. 优化性能

    • 设置合理的批量抓取大小(hibernate.default_batch_fetch_size
    • 只查询需要的列(DTO 投影)
    • 避免 N+1 查询问题

总结

通过本教程,你已经掌握了 Hibernate ORM 最核心的概念和基本操作:从环境配置、实体映射、Session 使用,到 CRUD、HQL 查询和事务处理。Hibernate 能极大提升数据库操作的开发效率,是 Java 生态中不可或缺的持久层技术。

接下来,你可以进一步学习 Hibernate 的高级特性:Criteria 查询、拦截器、事件监听器、多表映射、以及整合 Spring Boot 的最佳实践。带上今天的基础知识,继续深入探索 ORM 的世界吧!