1. 简介

在这篇文章中,我们将讨论 Hibernate 以及 Java Persistence API(JPA),并重点分析它们之间的区别。

我们会先从 JPA 是什么、怎么用以及它的核心概念开始入手。

然后,再看看 Hibernate 和 EclipseLink 在整个体系中扮演的角色。

2. 对象关系映射(ORM)

在深入 JPA 之前,我们有必要先理解 对象关系映射(Object-Relational Mapping,简称 ORM) 的概念。

简单来说,ORM 就是将 Java 对象直接持久化到数据库表的过程。通常,被持久化的对象名会成为表名,对象中的每个字段则对应表中的列。表结构确定后,每一行数据就对应应用中的一个记录。

3. JPA 概述

Java Persistence API(JPA)是一个规范,它定义了如何在 Java 应用中管理关系型数据。JPA 规范定义了一组概念,说明哪些对象需要被持久化,以及如何进行持久化。

⚠️注意:JPA 本身只是一个规范,它需要具体的实现才能工作——这一点我们稍后再详细讲。

接下来,我们来看看 JPA 实现必须涵盖的一些核心概念。

3.1. 实体(Entity)

javax.persistence.Entity 注解用于标记哪些对象需要被持久化到数据库。对于每个被标记的实体,JPA 会在数据库中创建一张对应的表。

此外,每个实体类都需要定义一个主键,使用 @Id 注解标记。配合 @GeneratedValue 注解,我们可以指定主键在数据插入时自动递增。

来看一个简单的实体示例:

@Entity
public class Car {
  
    @GeneratedValue
    @Id
    public long id;

    // getters and setters

}

不过,目前这段代码还不会对程序有任何影响——因为 JPA 本身并不提供任何实现代码。

3.2. 字段持久化

JPA 的另一个核心概念是字段持久化。当一个 Java 对象被定义为实体后,其所有字段默认都会被持久化为表中的列。

如果某个字段我们不希望被持久化,可以用 @Transient 注解将其标记为瞬态字段。

3.3. 关系映射

JPA 还规定了如何在应用中管理不同数据库表之间的关系。我们可以通过以下四个注解来描述:

  1. @OneToOne
  2. @OneToMany
  3. @ManyToOne
  4. @ManyToMany

举个例子:

@Entity
public class SteeringWheel {

    @OneToOne
    private Car car;

    // getters and setters
}

上面的代码表示 SteeringWheel 类与 Car 类之间是一对一的关系。

3.4. 实体管理器(EntityManager)

最后,javax.persistence.EntityManager 类定义了与数据库交互的操作。EntityManager 提供了常见的 CRUD 操作(增删改查),这些操作会被持久化到数据库中。

4. JPA 实现选择

JPA 只是一个规范,我们需要选择一个具体的实现来提供实际功能。否则,我们就得自己实现所有相关类,那可就太费劲了。

目前市面上有不少 JPA 实现可以选择,各有优劣。在选择时,建议从以下几个维度考虑:

  1. 项目成熟度 —— 这个实现存在多久了?文档是否完善?
  2. 生态支持 —— 有没有有用的子项目或工具?
  3. 社区支持 —— 出问题时有没有人能帮你解决?
  4. 性能表现 —— 这个实现的执行效率如何?

下面我们就来看看几种主流的 JPA 实现。

5. Hibernate

Hibernate 是一个成熟的 ORM 框架,同时也是 JPA 的一种实现。它是最流行的 JPA 实现之一,拥有庞大的社区支持。

Hibernate 实现了所有 javax.persistence 中定义的类,同时还提供了一些超出 JPA 规范的功能,例如:

虽然这些扩展功能很实用,但如果应用只需要基础的 JPA 功能,其实并不需要它们。

来看一个例子,Hibernate 在 @Entity 基础上提供了额外的元数据支持,比如:

@Table:指定实体对应的表名
@BatchSize:设置批量加载实体的数量

此外,Hibernate 还提供了一些 JPA 没有规定的功能,适合在大型项目中使用:

  1. 使用 @SQLInsert@SQLUpdate@SQLDelete 自定义 CRUD SQL 语句
  2. 支持软删除(soft delete)
  3. 使用 @Immutable 注解定义不可变实体

如需深入了解 Hibernate,可以参考我们的 Spring 持久层教程系列

EclipseLink 是由 Eclipse 基金会开发的开源 JPA 实现。除了 JPA,它还支持其他持久化标准,例如 Java Architecture for XML Binding(JAXB)。

简单来说,JAXB 可以将对象映射为 XML 格式,而非数据库表。

再来看 @Entity 的实现,EclipseLink 提供了不同的扩展。虽然没有像 Hibernate 那样的 @BatchSize,但它也提供了 Hibernate 所不具备的功能,例如:

@ReadOnly:标记实体为只读
@Struct:将类映射为数据库中的 struct 类型

如需了解更多 EclipseLink 的特性,可以参考我们的 EclipseLink 与 Spring 整合指南

7. 总结

这篇文章我们主要介绍了 Java Persistence API(JPA)的基本概念,并对比了 Hibernate 和 EclipseLink 这两种主流的 JPA 实现。

简单总结一下:

  • ✅ JPA 是一个规范,不是具体实现
  • ✅ Hibernate 是最成熟、生态最丰富的 JPA 实现之一
  • ✅ EclipseLink 是 Eclipse 基金会推出的开源 JPA 实现,支持多种持久化标准

选择哪种实现,最终还是要看项目需求、团队熟悉度和性能要求。


原始标题:The Difference Between JPA, Hibernate and EclipseLink | Baeldung