Ohhnews

分类导航

$ cd ..
Jetbrains Blog原文

Hibernate 7.4与IntelliJ IDEA逆向工程功能对比

#hibernate 7.4#intellij idea#逆向工程#jpa实体#数据库模式

在数据库驱动的应用开发中,逆向工程是指从现有数据库模式生成 Java 持久化工件,例如实体类和映射文件。

当数据库已经存在时,这非常有用,尤其是在遗留系统或大型项目中,手动创建实体类既慢又容易出错。

直到现在,这些功能由独立的 Hibernate Tools 项目提供。从 Hibernate 7.4 开始,核心 Hibernate Tools 模块已纳入 Hibernate 仓库。Maven、Gradle(甚至 Ant)用户现在可以通过 Hibernate 构建插件使用逆向工程。这对于数据库优先的项目尤其有用,在这种项目中,模式已经存在,而应用程序需要一组初始的持久化工件。

IntelliJ IDEA 也提供了逆向工程功能,可以帮助开发者从现有数据库生成 JPA 实体,从 JPA/JDBC 实体生成 Flyway 或 Liquibase 迁移等。

在本文中,让我们探索 Hibernate 7.4 和 IntelliJ IDEA 的逆向工程能力,并了解在哪种场景下使用哪个工具。

你可以在这篇GitHub 仓库中查看本文的示例代码。

Hibernate 7.4 逆向工程

Hibernate 7.4 可以检查现有数据库并生成如下工件:

  • JPA 实体类
  • Hibernate 映射文件
  • DAO 风格的辅助类
  • 数据库模式 SQL 脚本

示例项目中,逆向工程工作流通过 Maven 插件配置,并在 hibernate-reverse-engineering.xml 中指定了逆向工程自定义,如下所示:

$ xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering SYSTEM
        "https://hibernate.org/dtd/hibernate-reverse-engineering-3.0.dtd">
<hibernate-reverse-engineering>
    <type-mapping>
        <sql-type jdbc-type="NUMERIC" hibernate-type="big_decimal"/>
        <sql-type jdbc-type="OTHER" hibernate-type="pg-uuid"/>
    </type-mapping>

    <table-filter match-name=".*" package="com.jetbrains.entities"/>
    <table-filter match-name="flyway.*" exclude="true"/>

    <table name="products" class="Product">
        <primary-key property="id">
            <generator class="sequence">
                <param name="sequence_name">product_id_seq</param>
            </generator>
        </primary-key>
        <!-- other config -->
    </table>

    <!-- other tables config -->
</hibernate-reverse-engineering>

此配置允许我们自定义类型映射、包名、表过滤器、类名和主键生成。

pom.xml 中配置 hibernate-maven-plugin 如下:

$ xml
<properties>
   <!-- 更新为 Hibernate 的新版本 -->
   <hibernate.version>7.4.0.CR1</hibernate.version> 
</properties>

<plugin>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-maven-plugin</artifactId>
    <version>${hibernate.version}</version>
    <configuration>
        <revengFile>hibernate-reverse-engineering.xml</revengFile>
    </configuration>
    <executions>
        <execution>
            <id>generate-entities</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>hbm2ddl</goal>
                <goal>hbm2java</goal>
                <goal>hbm2dao</goal>
            </goals>
        </execution>
    </executions>
</plugin>

hbm2java 目标从数据库元数据生成 JPA 实体类,而 hbm2ddl 可生成数据库模式 SQL。hbm2dao 目标可生成 DAO 风格的辅助类,其中包含对实体执行 CRUD 操作的方法。

要生成工件,运行:

$ bash
$ ./mvnw generate-sources

此 Maven 目标在 target/generated-sources 中生成 JPA 实体和 DAO 类,在 target/generated-resources 目录中生成 schema.ddl 文件。

重新生成与版本控制工作流

生成的代码很少是应用模型的最终版本。在首次生成之后,开发者通常会添加验证注解、辅助方法、领域逻辑、抓取策略以及其他特定于项目的更改。

如果稍后重新生成这些文件,手动更改可能会被覆盖。这就是为什么当开发者直接编辑生成的实体时,重新生成工作流可能并不理想。

然而,重新生成并非总是缺点。有些团队更倾向于将逆向工程配置保留在源代码控制中,并将生成作为构建的一部分。在这种设置下,输出是可重复的,可以在 CI/CD 中工作,并且不依赖于特定 IDE。

例如,CI 检查可以重新生成工件,如果生成的文件与已提交的版本不同,则构建失败。

这种工作流也适用于版本化的数据库迁移。迁移脚本可以保持作为模式历史的唯一真实来源,而 Hibernate 逆向工程则从当前数据库模式生成 Java 工件。

Hibernate 还内置了模式更新机制,并且逆向工程的输出可以通过自定义的 RevengineeringStrategy 进一步定制,因此底层模型不必是僵化、一刀切的脚本。

IntelliJ IDEA 逆向工程

IntelliJ IDEA 提供了更具交互性和灵活性的逆向工程工作流。无需创建和维护逆向工程 XML 文件,我们可以直接从 IDE 连接到数据库,选择表,并直接生成 JPA 实体。

更重要的是,IntelliJ IDEA 支持数据库模式与代码之间的渐进式同步。当数据库发生变化时,IDE 可以帮助将这些变化同步到现有的实体类中,而无需强制进行完全重新生成。这有助于保留在初始生成之后所做的手动修改。

这种差异在实际项目中很重要。实体类往往会成为领域模型的一部分,而不仅仅是生成的数据库镜像。能够安全地演化已生成的实体比反复重新创建它们更有价值。

此功能由 IntelliJ IDEA Ultimate 提供,因此你需要订阅。它(目前)在 IntelliJ IDEA Community Edition 或其他 IDE 中不可用,也无法作为构建管道中的命令行步骤运行。

更丰富、更灵活的功能

除了从表生成 JPA 实体之外,IntelliJ IDEA 的逆向工程还提供其他功能。IDE 支持相关的工作流,例如:

  • 从现有数据库模式生成 JPA 实体
  • 将数据库更改同步到现有实体类
  • 在增量更新期间保留手动更改
  • 从 JPA 实体生成 Flyway 迁移
  • 从 JPA 实体生成 Liquibase 迁移
  • 除了 JPA 之外,还支持 Spring Data JDBC 实体

要了解这些功能的更多信息,请浏览以下文章:

这使得 IntelliJ IDEA 更适合日常开发,尤其是在模式和代码共同演化的情况下。它提供了引导式工作流、可视化数据库集成以及增量更新,无需针对每次更改都配置构建时生成。

选择正确的工作流

当我们想要一个可重复、构建驱动的过程时,Hibernate 7.4 逆向工程是一个强有力的选择。它特别适合从现有数据库生成实体和模式 SQL 的初始版本,尤其是在自动化工作流中。

当我们想要一个迭代式工作流时,IntelliJ IDEA 更合适。它帮助开发者逐步同步代码和数据库更改,而不会丢失手动实体定制。它还支持围绕迁移和 Spring Data JDBC 的额外工作流,使其在应用程序开发方面功能更丰富、更灵活。

总结

两种方法都解决了从现有数据库模式生成 Java 持久化工件的核心问题,但它们适用于不同的场景。

在以下情况使用 Hibernate 7.4 逆向工程:

  • 你希望将生成作为构建过程的一部分,以基于当前数据库模式生成实体、DAO、.hbm 文件。
  • 你需要此功能在任何 IDE 中,或从命令行,或在 CI/CD 管道中工作,因为它通过 Gradle 或 Maven 运行。
  • 你愿意从版本控制的 reveng.xml 文件重新生成实体、DAO 和 .hbm 文件,而不是手动编辑生成的代码。

在以下情况使用 IntelliJ IDEA 逆向工程:

  • 你想要一种交互式、可视化的方式生成实体,无需编写任何 XML 配置。
  • 你的数据库模式随时间变化,你需要保持实体类同步,而不会丢失你已添加的自定义逻辑。
  • 除了 JPA 之外,你还在使用 Spring Data JDBC,或者你需要生成 Flyway 或 Liquibase 迁移脚本。
  • 你拥有 IntelliJ IDEA Ultimate 订阅,并且不需要逆向工程在 IDE 之外运行(例如,在 CI/CD 管道中)。

IntelliJ IDEA 通常是日常开发的强有力选择,因为它允许你共同演化数据库和 Java 模型,只要你拥有 Ultimate 订阅并且不需要在 IDE 之外运行该步骤。它能理解代码中已有的内容,并能将模式更改合并到其中,而不是从头替换所有内容。

如果你的团队需要此功能在任何 IDE 中运行,或作为 CI/CD 管道的一部分运行,或者你更喜欢版本化、可重复的生成步骤,那么 Hibernate 7.4 基于构建工具的逆向工程是更合适的选择。

如果你正在从一个现有数据库开始一个全新的项目,那么任何一种方法都能为你提供一个坚实的起点。从那以后,正确的选择主要取决于你团队的工作流和工具限制。