杰瑞科技汇

Hibernate 4教程怎么学?

Hibernate 4 教程:从入门到实践

目录

  1. 第一部分:Hibernate 简介

    Hibernate 4教程怎么学?-图1
    (图片来源网络,侵删)
    • 什么是 ORM?
    • Hibernate 是什么?
    • 为什么使用 Hibernate?
    • Hibernate 4 的核心组件
  2. 第二部分:环境搭建

    • 准备工作
    • 创建 Maven 项目
    • 添加 Hibernate 4 和 MySQL 驱动依赖
  3. 第三部分:第一个 Hibernate 程序 (Hello World)

    • 数据库准备
    • 创建实体类
    • 创建映射文件
    • 创建 Hibernate 配置文件
    • 编写核心 Java 代码
    • 运行与测试
  4. 第四部分:Hibernate 核心 API

    • Configuration: 配置加载
    • ServiceRegistry: 服务注册中心 (Hibernate 4 的关键)
    • SessionFactory: 工厂类
    • Session: 交互接口
    • Transaction: 事务管理
    • Query / Criteria: 查询接口
  5. 第五部分:CRUD 操作详解

    Hibernate 4教程怎么学?-图2
    (图片来源网络,侵删)
    • 创建 - save() / persist()
    • 读取 - get() / load()
    • 更新 - update() / merge()
    • 删除 - delete()
    • HQL (Hibernate Query Language) 简介
  6. 第六部分:关联关系映射

    • 多对一
    • 一对多
    • 一对一
    • 多对多
  7. 第七部分:进阶特性

    • 缓存机制 (一级缓存和二级缓存)
    • 事务与并发

第一部分:Hibernate 简介

1 什么是 ORM?

ORM (Object-Relational Mapping),即“对象关系映射”,是一种编程技术,用于将面向对象模型与关系型数据库的数据结构进行映射,它允许开发者使用面向对象的方式来操作数据库,而无需编写繁琐的 SQL 语句。

  • Java 对象数据库表
  • 对象属性表的列
  • 对象实例表的行

2 Hibernate 是什么?

Hibernate 是一个开源的、基于 ORM 模式的持久层框架,它对 JDBC 进行了轻量级的封装,使得 Java 开发者可以以面向对象的方式操作数据库。

3 为什么使用 Hibernate?

  • 提高开发效率:告别手写复杂的 SQL 语句,专注于业务逻辑。
  • 面向对象编程:代码更符合 Java 的编程思想,易于理解和维护。
  • 数据库无关性:通过更换方言,可以轻松地将项目从一种数据库(如 MySQL)迁移到另一种(如 Oracle)。
  • 强大的缓存机制:提供一级缓存和二级缓存,提升数据读取性能。
  • 简化数据操作:提供了丰富的 API 来处理增删改查、关联关系等复杂操作。

4 Hibernate 4 的核心组件

Hibernate 4 引入了一个重要的变化:ServiceRegistry,它取代了早期版本中直接使用 Configuration 构建 SessionFactory 的方式,使得配置更加灵活和模块化。

  • Configuration: 负责加载和读取 Hibernate 的配置信息(如 hibernate.cfg.xml)和映射文件(.hbm.xml)。
  • ServiceRegistry: 一个服务注册中心,用于管理 Hibernate 所需的各种服务(如连接池、事务工厂、缓存等)。这是 Hibernate 4 的核心入口。
  • SessionFactory: 线程安全的重量级对象,它是 Session 的工厂,一个数据库对应一个 SessionFactory
  • Session: 轻量级非线程安全的对象,是 Java 应用程序与数据库交互的主要接口,它相当于 JDBC 中的 Connection
  • Transaction: 管理事务,确保数据操作的原子性。
  • Query / Criteria: 执行查询的接口,Query 用于 HQL 查询,Criteria 用于面向对象的、类型安全的查询。

第二部分:环境搭建

1 准备工作

  1. JDK 1.7 或更高版本
  2. IDE (如 IntelliJ IDEA 或 Eclipse)
  3. MySQL 数据库
  4. Maven (用于依赖管理)

2 创建 Maven 项目

在你的 IDE 中创建一个新的 Maven 项目。

3 添加依赖

打开 pom.xml 文件,添加以下依赖,我们使用 Hibernate 4.2.21 (一个稳定的 4.x 版本) 和 MySQL 5.1.38 驱动。

<dependencies>
    <!-- Hibernate 4 Core -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.2.21.Final</version>
    </dependency>
    <!-- MySQL Connector/J -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
    </dependency>
    <!-- (可选) JUnit 用于测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

第三部分:第一个 Hibernate 程序

我们将创建一个简单的 User 实体,并将其保存到数据库中。

1 数据库准备

在 MySQL 中创建一个数据库和一张表。

CREATE DATABASE hibernate_demo;
USE hibernate_demo;
CREATE TABLE `user` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) NOT NULL,
  `email` VARCHAR(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

2 创建实体类

创建一个 User.java 文件,它是一个普通的 Java Bean。

// src/main/java/com/example/entity/User.java
package com.example.entity;
public class User {
    private Long id;
    private String name;
    private String email;
    // 无参构造器 (Hibernate 反射需要)
    public User() {
    }
    // Getters and Setters
    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;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

3 创建映射文件

src/main/resources 目录下,创建 User.hbm.xml 文件,用于告诉 Hibernate 如何将 User 类映射到 user 表。

<!-- src/main/resources/User.hbm.xml -->
<?xml version="1.0"?>
<!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="user">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>
        <property name="email" column="email"/>
    </class>
</hibernate-mapping>

4 创建 Hibernate 配置文件

src/main/resources 目录下,创建 hibernate.cfg.xml 文件,配置数据库连接信息和 Hibernate 全局属性。

<!-- src/main/resources/hibernate.cfg.xml -->
<?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.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_demo</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.MySQL5Dialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!--
            show_sql: 在控制台打印生成的 SQL 语句。
            format_sql: 格式化输出的 SQL 语句。
            hbm2ddl.auto: 自动管理表结构。
                - update: 如果模型有变化,自动更新表结构(开发环境推荐)。
                - create: 每次启动都删除并重建表(测试环境)。
                - none: 不做任何操作(生产环境推荐)。
        -->
        <!-- 3. 映射文件 -->
        <mapping resource="User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

5 编写核心 Java 代码

创建一个 HibernateUtil 工具类来获取 SessionFactory,以及一个 MainApp 类来执行操作。

HibernateUtil.java

// src/main/java/com/example/util/HibernateUtil.java
package com.example.util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
    private static final SessionFactory sessionFactory;
    static {
        try {
            // 1. 加载配置文件
            Configuration configuration = new Configuration().configure();
            // 2. 创建 ServiceRegistry (Hibernate 4 的关键步骤)
            StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
                    .applySettings(configuration.getProperties())
                    .build();
            // 3. 使用配置和注册表创建 SessionFactory
            sessionFactory = configuration.buildSessionFactory(registry);
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

MainApp.java

// src/main/java/com/example/MainApp.java
package com.example;
import com.example.entity.User;
import com.example.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
public class MainApp {
    public static void main(String[] args) {
        // 1. 获取 SessionFactory
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        // 2. 打开 Session
        Session session = sessionFactory.openSession();
        // 3. 开启事务
        Transaction transaction = null;
        try {
            transaction = session.beginTransaction();
            // 4. 创建 User 对象
            User user = new User();
            user.setName("John Doe");
            user.setEmail("john.doe@example.com");
            // 5. 保存 User 对象
            session.save(user);
            // 6. 提交事务
            transaction.commit();
            System.out.println("User saved successfully! ID: " + user.getId());
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback(); // 出错则回滚
            }
            e.printStackTrace();
        } finally {
            // 7. 关闭 Session
            session.close();
        }
        // 8. 关闭 SessionFactory
        sessionFactory.close();
    }
}

6 运行与测试

运行 MainApp.javamain 方法。

  • 你会在控制台看到 Hibernate 生成的 CREATE TABLEINSERT SQL 语句。
  • 登录你的 MySQL 数据库,查询 user 表,会发现已经成功插入了一条数据。

第四部分:Hibernate 核心 API

我们已经在上面的例子中接触了这些核心 API,这里再详细解释一下它们的作用和关系。

  1. Configuration:

    • 作用:读取配置文件(hibernate.cfg.xml)和映射文件(.hbm.xml)。
    • 在 Hibernate 4 中,它仍然是配置的起点。
  2. StandardServiceRegistry (ServiceRegistry):

    • Hibernate 4 的核心,它是一个服务注册中心,管理着 Hibernate 运行时所需的所有服务(如连接池、事务工厂、缓存提供商等)。
    • 通过 StandardServiceRegistryBuilder 构建,并将 Configuration 的属性应用到这些服务上。
  3. SessionFactory:

    • ConfigurationServiceRegistry 共同构建。
    • 它是重量级对象,创建和销毁成本高,通常一个应用只创建一个 SessionFactory 实例。
    • 它是线程安全的,可以被多个线程共享。
    • 主要作用是生产 Session 对象。
  4. Session:

    • 轻量级对象,不是线程安全的,因此不能被多个线程共享。
    • 它是应用程序与数据库进行交互的“门面”,相当于一个“工作单元”。
    • 负责执行 CRUD 操作、管理事务、管理一级缓存。
  5. Transaction:

    • 代表一次原子性操作(一个或多个 SQL 语句)。
    • 必须显式地开始(beginTransaction())和提交(commit()),如果发生异常则回滚(rollback())。
  6. Query / Criteria:

    • Query: 用于执行 HQL(Hibernate Query Language)查询,HQL 是一种面向对象的查询语言,语法类似于 SQL,但操作的是类和属性而不是表和列。
    • Criteria: 提供了一种更面向对象、类型安全的方式来构建查询,无需手写 HQL 字符串。

第五部分:CRUD 操作详解

基于上面的 User 实体,我们演示完整的 CRUD 操作。

// 假设我们有一个 SessionFactory 实例
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
try {
    // C: Create (创建)
    User newUser = new User();
    newUser.setName("Alice");
    newUser.setEmail("alice@example.com");
    session.save(newUser); // 插入
    System.out.println("Created: " + newUser);
    // R: Read (读取)
    // get(): 立即加载,如果对象不存在返回 null
    User user1 = (User) session.get(User.class, 1L); // 假设 ID 为 1
    System.out.println("Get by ID 1: " + user1);
    // load(): 延迟加载(返回代理对象),只有当访问对象属性时才真正去查询数据库,如果对象不存在,抛出 ObjectNotFoundException
    User user2 = (User) session.load(User.class, 2L);
    System.out.println("Load by ID 2: " + user2.getName()); // 这里才真正执行查询
    // U: Update (更新)
    if (user1 != null) {
        user1.setEmail("alice_updated@example.com");
        session.update(user1); // 更新
        System.out.println("Updated: " + user1);
    }
    // D: Delete (删除)
    if (user2 != null) {
        session.delete(user2); // 删除
        System.out.println("Deleted user with ID 2");
    }
    transaction.commit();
} catch (Exception e) {
    if (transaction != null) {
        transaction.rollback();
    }
    e.printStackTrace();
} finally {
    session.close();
}

save(), update(), merge() 的区别:

  • save(): 将一个临时状态的对象变为持久状态,并分配一个 ID,如果对象已经有 ID,会抛异常。
  • update(): 将一个游离状态(有 ID 但不在 Session 缓存中)的对象与 Session 关联,并同步到数据库,如果对象没有 ID,会抛异常。
  • merge(): 更智能的更新方法,它会将对象的属性复制到持久状态对象中,并更新,Session 中没有对应的持久对象,它会从数据库加载一个,然后更新,通常推荐使用 merge() 来处理可能游离的对象。

第六部分:关联关系映射

关联关系是 ORM 的核心,我们以 UserRole(角色)为例,演示一对多关系。

场景: 一个用户可以有多个角色(如管理员、普通用户、访客),一个角色可以被多个用户拥有,这是一个典型的多对多关系,但为了演示,我们先简化成一对多:一个用户可以有多个地址。

1 多对一

场景: 多个 Address 属于一个 User

  1. 创建 Address 实体和映射文件

    // Address.java
    package com.example.entity;
    public class Address {
        private Long id;
        private String street;
        private String city;
        private User user; // 关联到 User
        // getters, setters, constructor...
    }
    <!-- Address.hbm.xml -->
    <hibernate-mapping package="com.example.entity">
        <class name="Address" table="address">
            <id name="id" column="id">
                <generator class="native"/>
            </id>
            <property name="street" column="street"/>
            <property name="city" column="city"/>
            <!-- 多对一映射 -->
            <many-to-one name="user" class="User" column="user_id" not-null="true"/>
        </class>
    </hibernate-mapping>
    • name="user": Address 实体中关联的属性名。
    • class="User": 关联的实体类。
    • column="user_id": 在 address 表中,外键的列名。
  2. User.hbm.xml 中添加一对多映射

    <!-- User.hbm.xml -->
    <class name="User" table="user">
        <!-- ... id 和 property ... -->
        <!-- 一对多映射 -->
        <set name="addresses" table="address" cascade="save-update,delete-orphan" inverse="true">
            <key column="user_id"/>
            <one-to-many class="com.example.entity.Address"/>
        </set>
    </class>
    • <set>: 表示这是一个 Set 集合(地址不能重复)。
    • name="addresses": User 实体中存放地址集合的属性名。
    • cascade="save-update,delete-orphan": 级联操作,保存或更新用户时,自动保存其地址;当从用户的地址集合中移除一个地址时,自动删除该地址。
    • inverse="true": 将关系维护权交给对方(Address),这可以避免在更新两端时生成冗余的 update 语句。强烈建议在“一”的一方设置 inverse="true"

第七部分:进阶特性

1 缓存机制

Hibernate 提供了两级缓存来减少数据库访问次数,提升性能。

  • 一级缓存 (Session-Level Cache):

    • 作用域:Session
    • 特性:Session 一关闭,缓存就失效,它是 Hibernate 自带的,无法关闭。
    • 作用:在同一个 Session 内部,多次获取同一个对象,只会发一次 SQL 查询。
  • 二级缓存 (SessionFactory-Level Cache):

    • 作用域:SessionFactory
    • 特性:可以被所有 Session 共享,生命周期与 SessionFactory 相同,需要额外配置和第三方缓存提供商(如 Ehcache)。
    • 作用:在不同 Session 之间共享数据,避免重复查询数据库。

配置二级缓存(以 Ehcache 为例):

  1. 添加 ehcachehibernate-ehcache 依赖。
  2. hibernate.cfg.xml 中启用二级缓存。
    <property name="hibernate.cache.use_second_level_cache">true</property>
    <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
    <property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>
  3. src/main/resources 下创建 ehcache.xml 文件进行配置。
  4. 在需要缓存的实体类的映射文件中,使用 <cache/> 标注。
    <class name="com.example.entity.User" table="user">
        <cache usage="read-write"/> <!-- read-write, read-only, transactional -->
        <!-- ... -->
    </class>

2 事务与并发

  • 事务边界: 一个事务应该从一个明确的 beginTransaction() 开始,到 commit()rollback() 结束,一个业务方法通常对应一个事务。
  • 并发问题: 当多个事务同时操作同一数据时,可能产生脏读、不可重复读、幻读等问题。
  • 隔离级别: 数据库通过隔离级别来控制并发,Hibernate 允许你通过配置设置隔离级别。
    <property name="hibernate.connection.isolation">2</property>
    <!-- 1: READ_UNCOMMITTED, 2: READ_COMMITTED, 4: REPEATABLE_READ, 8: SERIALIZABLE -->
  • 乐观锁: 通过在表中增加一个版本号(version)或时间戳(timestamp)字段来实现,当更新数据时,检查版本号是否与读取时一致,如果一致才更新,否则失败。
    <class name="User" table="user">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <version name="version" column="version"/> <!-- 乐观锁 -->
        <!-- ... -->
    </class>

总结与 Hibernate 5/6 的提示

本教程详细介绍了 Hibernate 4 的核心概念和使用方法,Hibernate 4 引入了 ServiceRegistry,使得配置更加灵活和模块化,这是与 Hibernate 3 最大的区别。

重要提示:

  • Hibernate 4 已经进入维护模式,官方不再推荐在新项目中使用。
  • Hibernate 5Hibernate 6 是当前的主流版本,它们带来了许多重大改进:
    • Hibernate 5: 引入了 JPA 2.1 支持、更好的类型系统、对 Java 8 的支持等。
    • Hibernate 6: 引入了革命性的 Jakarta EE 9/10 支持(包名从 javax.persistence 变为 jakarta.persistence)、大幅提升性能、简化配置等。

如果你要开始一个新项目,强烈建议直接学习 Hibernate 5 或 6,本教程为你打下的坚实基础(如 ORM 思想、核心 API、关联映射、缓存、事务等)在更高版本中同样适用,只是配置方式和部分 API 可能有所不同,在 Hibernate 5+ 中,获取 SessionFactory 的方式更加简化:

// Hibernate 5+ 方式
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
// 或者使用更现代的 StandardServiceRegistry 方式(与 Hibernate 4 类似,但包名略有变化)

希望这份教程能帮助你顺利入门 Hibernate 4!

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