杰瑞科技汇

Hibernate教程从哪开始学?

Hibernate 使用教程:从入门到精通

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

Hibernate教程从哪开始学?-图1
(图片来源网络,侵删)

目录

  1. 核心概念
    • 什么是 ORM?
    • Hibernate 的核心组件
    • Hibernate 的工作原理
  2. 环境准备
    • JDK
    • IDE (IntelliJ IDEA / Eclipse)
    • Maven
    • 数据库
  3. 第一个 Hibernate 程序 (Hello World)
    • 步骤 1: 创建 Maven 项目
    • 步骤 2: 添加依赖
    • 步骤 3: 创建实体类
    • 步骤 4: 创建映射文件
    • 步骤 5: 创建 Hibernate 配置文件
    • 步骤 6: 编写测试代码
    • 步骤 7: 运行与结果分析
  4. Hibernate 核心 API
    • Configuration
    • ServiceRegistry
    • Metadata
    • SessionFactory
    • Session
    • Transaction
    • Query vs Criteria
  5. Hibernate CRUD 操作详解
    • 保存
    • 查询
    • 更新
    • 删除
  6. 进阶主题
    • 关系映射 (一对一、一对多、多对多)
    • HQL (Hibernate Query Language)
    • 缓存机制
  7. 最佳实践与总结

核心概念

1 什么是 ORM?

ORM 是一种编程技术,用于将对象模型与关系型数据库的数据结构之间进行映射,通过 ORM,开发者可以用操作对象的方式(如 user.setName("张三"))来间接操作数据库,而 ORM 框架会自动将其转换为对应的 SQL 语句(如 UPDATE users SET name = '张三' WHERE id = 1)。

优点:

  • 提高开发效率:无需编写大量重复的 JDBC 代码。
  • 面向对象:代码更易于理解和维护。
  • 数据库无关性:更换数据库时,只需修改少量配置,业务代码基本不变。

2 Hibernate 的核心组件

  • Configuration:负责配置并启动 Hibernate,读取 hibernate.cfg.xmlpersistence.xml 文件。
  • SessionFactory:线程安全的重量级对象,是生产 Session 的工厂,它代表了数据库的连接池,一个数据库对应一个 SessionFactory
  • Session:轻量级非线程安全的对象,相当于 JDBC 中的 Connection,它是应用程序与数据库交互的主要接口,用于执行 CRUD 操作。
  • Transaction:管理事务,确保数据的一致性。
  • Persistent Object (PO) / Entity Bean:与数据库表映射的 Java 对象。
  • Mapping File:XML 文件(或注解),用于定义 PO 与数据库表之间的映射关系。

3 Hibernate 的工作原理

  1. 读取并解析配置文件 (hibernate.cfg.xml) 和映射文件 (.hbm.xml 或注解)。
  2. 创建 Configuration 对象,并根据配置创建一个 SessionFactory 对象。
  3. 应用程序从 SessionFactory 中获取一个 Session 对象。
  4. 开启一个事务 (Transaction)。
  5. 通过 Session 对象与数据库进行交互(CRUD)。
  6. 提交事务或回滚事务。
  7. 关闭 SessionSessionFactory

环境准备

  • JDK 8+
  • IDE: IntelliJ IDEA 或 Eclipse
  • Maven: 用于管理项目依赖
  • 数据库: MySQL (本教程以 MySQL 为例)

第一个 Hibernate 程序

我们将创建一个简单的程序,向数据库中插入一条用户信息。

步骤 1: 创建 Maven 项目

在 IDE 中创建一个新的 Maven 项目,选择 maven-archetype-quickstart 模板。

Hibernate教程从哪开始学?-图2
(图片来源网络,侵删)

步骤 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),但注解更方便。

Hibernate教程从哪开始学?-图3
(图片来源网络,侵删)

步骤 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&amp;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();
        }
    }
}

注意SessionFactorySession 的创建和关闭是比较耗时的操作,在实际项目中,SessionFactory 通常作为单例,而 Session 是非线程安全的,应在每个线程中创建和关闭。

步骤 7: 运行与结果分析

  1. 准备数据库:在 MySQL 中创建一个名为 hibernate_demo 的数据库。
    CREATE DATABASE hibernate_demo;
  2. 运行测试:在 IDE 中运行 testSaveUser() 方法。
  3. 查看结果
    • 控制台:你会看到 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 核心 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 和实体类上配置)。

最佳实践与总结

  1. 使用注解:在现代 Java 开发中,使用 JPA 注解进行映射是绝对的主流,比 XML 映射文件更简洁、更易于维护。
  2. SessionFactory 管理SessionFactory 是重量级对象,应该在整个应用生命周期中只创建一次,通常使用单例模式或依赖注入(如 Spring 框架)来管理。
  3. Session 管理Session 是轻量级且非线程安全的,不要在多个线程间共享它,最佳实践是“一次请求,一个 Session”,在请求开始时打开,在请求结束时关闭。
  4. 事务管理:确保所有数据库操作都在事务中完成,推荐使用声明式事务管理(如 Spring 的 @Transactional),而不是编程式事务。
  5. 合理使用 HQL:HQL 强大且灵活,但要注意 SQL 注入风险(使用参数绑定),对于简单的 CRUD,Hibernate 的 Criteria API 或 JPA 的 EntityManager API 也是不错的选择。
  6. 了解缓存:合理利用一级和二级缓存可以显著提升应用性能,但要警惕缓存带来的数据一致性问题。
  7. 选择合适的主键生成策略IDENTITY (自增) 适合 MySQL,SEQUENCE 适合 Oracle,UUID 适合分布式系统。

Hibernate 是一个非常成熟的 ORM 框架,极大地简化了数据库操作,掌握其核心概念、配置和 API 是进行 Java 企业级开发的基础,随着 JPA 标准的普及,Hibernate 作为其最优秀的实现之一,依然是开发者不可或缺的工具。

分享:
扫描分享到社交APP
上一篇
下一篇