IntelliJ IDEA 2026.2 Help

逆向工程

逆向工程是基于数据库模式搭建 JPA 实体类的过程。

从数据库生成 JPA 实体

  1. 如果尚未建立数据库连接,请 创建一个

  2. 数据库 工具窗口中,展开 JPA 节点,右键点击数据库或特定表,然后选择 新建 | 从数据库中获取 JPA 实体

    从数据库创建 JPA 实体
  3. 选择要映射的数据库连接、表和属性。 有关更多信息,请参见 来自 DB Wizard 的实体

在您的 IDE 打开期间,数据库可能会被其他客户端修改。 要从数据库获取最新数据,您可以在 从数据库生成实体 窗口或 数据库 工具窗口中点击

来自 DB Wizard 的实体

数据库窗口中的实体

配置

窗口顶部的菜单允许您配置:

  • 数据库连接

  • 生成实体将保存的源根目录和包

  • 是否需要迁移索引和约束

  • 是否应在 @Table 注解中指定 schema 名称

此外,您还可以从 其他设置 下拉列表中,转到 实体声明逆向工程 设置。

映射关系、表和视图

在窗口的左侧,您可以看到:

  • 映射关系:映射到 JPA 实体的表和视图

  • 数据库中存在但未映射到实体的表

  • 视图:数据库中存在但未映射到实体的视图

选择树中的任意元素后,将出现一个用于从列迁移属性的面板。 此外,您将能够在相应字段中定义 class name。

迁移属性

窗口的主要部分允许您配置与属性相关的所有内容。 您可以选择要添加的属性,并更改它们的所有参数, 列名 除外。 映射类型和属性 / 转换器 / hibernate 类型表示为下拉列表。

所有属性分为 3 类:

  • 已迁移列——已存在于实体中的列(仅适用于映射关系)

  • 列 - 尚未在实体或父 @MappedSuperclass 中映射的新列

  • 引用——在观察到的表格中未表示为列的可选关联

父实体

IntelliJ IDEA 提供通过从 @MappedSuperclass 注释的类中选择一个类以定义父实体的功能,这可以在 父项 下拉框中完成。 这允许生成的实体扩展自父类,并自动继承所有具有相同名称和类型的属性。

@MappedSuperclass 中的列名与子实体的表不匹配的情况下,我们仍然可以使用 @AttributeOverride 注解继承该属性。 通过简单地选择属性名称并选择要覆盖的属性,IntelliJ IDEA 可以帮助管理继承。

attribute-override.png

在生成实体期间,IntelliJ IDEA 如果检测到数据库中缺少来自 @MappedSuperclass 的任何继承属性,会发出警报。 要使模型与数据库对齐,请访问 JPA Structure 菜单中的 通过实体生成 DDL 操作并选择 现有数据库更新 选项。

创建枚举

对于匹配 StringInteger 类型的属性,您可以将映射类型从 Basic 更改为 Enum,然后 IntelliJ IDEA 会在项目中创建相应的 Enum 类。 您需要手动填充 enum 的适当值。

处理未知类型

对于某些 SQL 类型,没有与 Java 类完全匹配的对应关系。 在这种情况下,IntelliJ IDEA 不设置类型,以防止生成无效的代码。 您需要自己选择属性类型。 您还可以在 设置中为每个 DBMS 配置默认类型映射。

如果您的项目依赖列表中有 HibernateTypes 库,IntelliJ IDEA 在逆向工程过程中可以自动为不支持的 SQL 类型建议适合的库类型:

// TODO 注释

如果您想推迟特定列的属性创建,您可以选择 //todo comment 作为映射类型。 IntelliJ IDEA 会根据列类型生成 //todo 注释及相应的快速修复操作。 您可以按 Ctrl+B 执行这些操作:

  • 对于已知的基本和关联类型,您可以:

    • 按原样取消注释

    • 移除列映射

  • 对于未知的 column 类型,您可以:

    • 定义目标 Java 类型

    • 按原样取消注释

    • 移除列映射

这里是为具有未知列类型的属性生成的 //todo 注释示例:

/* TODO [Reverse Engineering] create field to map the 'description' column Available actions: Define target Java type | Uncomment as is | Remove column mapping @Column(name = "description", columnDefinition = "jsonb") private java.lang.Object description; */

调用 定义目标 Java 类型 操作后,将出现以下窗口:

mapping-java-type

IntelliJ IDEA 将记住数据映射以供后续的逆向工程操作使用。 您可随时在 设置中更改它们。

将数据库视图映射到 JPA 实体

IntelliJ IDEA 遵循所有最佳实践,在逆向工程时为数据库视图提供最有效的映射:

  1. 由于数据库视图没有主键,IntelliJ IDEA 允许您选择一个字段或一组字段作为目标实体的标识符。

  2. 大多数 DB 视图是不可变的。 因此,IntelliJ IDEA 向实体添加 @Immutable 注解并且仅生成getters。 这有助于提高应用程序性能。

  3. 根据 JPA 规范,对于映射到数据库视图的实体,IntelliJ IDEA 仅生成一个无参 protected 构造函数,从而防止开发人员在业务逻辑代码中创建此类实体的新实例。

逆向工程列

一些开发人员更喜欢 DB-first 应用程序开发方法。 首先, 他们直接向数据库添加列,然后更新 JPA 模型。 IntelliJ IDEA 可以自动化此过程。

从数据库生成属性

  1. 如果尚未建立数据库连接,请 创建一个

  2. 持久化 工具窗口中,展开 JPA 节点,右键点击实体,然后选择 新建 | 从数据库中获取 JPA 实体

    或者,在您的实体源代码中,点击装订线中的实体图标 实体图标 ,然后选择 从数据库创建实体属性

  3. 请选择一个数据库连接、一张表或一个视图,并选择要映射的列。 属性迁移流程与 从数据库生成实体向导 部分所述一致。

    数据库对话框中的实体属性

智能引用检测

IntelliJ IDEA 深刻理解您的模型。 在某些情况下,可以正确检测基数: @OneToOne@OneToMany@ManyToOne@ManyToMany。 最酷的是,IntelliJ IDEA 即使在当前表格中没有相应列的情况下也能显示引用。

让我们更仔细地看看这些情况。

@OneToOne

在两种情况下,我们可以自信地假设关系的基数为 @OneToOne

  1. 表中有一列带有唯一约束,引用了另一个表的主键

  2. 表的主键是外键

情况 1:

CREATE TABLE profiles ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, join_date date, user_id BIGINT, status VARCHAR(255), bio VARCHAR(255), CONSTRAINT pk_profiles PRIMARY KEY (id) ); CREATE TABLE users ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, last_name VARCHAR(255), first_name VARCHAR(255), CONSTRAINT pk_users PRIMARY KEY (id) ); ALTER TABLE profiles ADD CONSTRAINT uc_profiles_user UNIQUE (user_id); ALTER TABLE profiles ADD CONSTRAINT FK_PROFILES_ON_USER FOREIGN KEY (user_id) REFERENCES users (id);
one-to-one-uc-diagram.jpeg
one-to-one-uc-wizard

IntelliJ IDEA将在 User 实体中生成一个 @OneToOne 关联,具有一个 @JoinColumn 注解,并在 Profile 实体中生成一个 @OneToOne 关联,具有一个 mappedBy 参数:

@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "profile_id") private Profile profile; } @Entity @Table(name = "profiles") public class Profile { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @OneToOne(fetch = FetchType.LAZY, mappedBy = "profile") private User users; }

案例编号 2:

CREATE TABLE users ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, last_name VARCHAR(255), first_name VARCHAR(255), CONSTRAINT pk_users PRIMARY KEY (id) ); CREATE TABLE profiles ( user_id BIGINT NOT NULL, status VARCHAR(255), bio VARCHAR(255), join_date date, CONSTRAINT pk_profiles PRIMARY KEY (user_id) ); ALTER TABLE profiles ADD CONSTRAINT FK_PROFILES_ON_USER FOREIGN KEY (user_id) REFERENCES users (id);
one-to-one-pk-fk-diagram.jpeg
one-to-one-pk-fk-wizard.jpeg

由于 @Id 不应是持久化实体,IntelliJ IDEA 将生成:

  • 基本类型的 id 属性并使用 @Id 注解对其进行标记

  • users@OneToOne 关联并使用 @MapsId 注解标记

@Entity @Table(name = "profiles") public class Profile { @Id @Column(name = "user_id", nullable = false) private Long id; @MapsId @OneToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "user_id", nullable = false) private User users; //... } @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @OneToOne(fetch = FetchType.LAZY, mappedBy = "user") private Profile profiles; //... }

@OneToMany & @ManyToOne

如果一个表具有指向另一个表的主键的列,则很可能是一个 @ManyToOne 关联。 但是您也可以根据需要将基数更改为 @OneToOne。 因此,取决于您在哪个表上调用反向工程操作,IntelliJ IDEA 将检测映射类型为 @OneToMany@ManyToOne

CREATE TABLE users ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, last_name VARCHAR(255), first_name VARCHAR(255), CONSTRAINT pk_users PRIMARY KEY (id) ); CREATE TABLE profiles ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, join_date date, status VARCHAR(255), bio VARCHAR(255), user_id BIGINT, CONSTRAINT pk_profiles PRIMARY KEY (id) ); ALTER TABLE profiles ADD CONSTRAINT FK_PROFILES_ON_USER FOREIGN KEY (user_id) REFERENCES users (id);
one-to-many-many-to-one-diagram
one-to-many-many-to-one-wizard

IntelliJ IDEA 将生成以下代码:

@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @OneToMany(mappedBy = "user") private Set<Profile> profiles = new LinkedHashSet<>(); //... } @Entity @Table(name = "profiles") public class Profile { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; //... }

@ManyToMany

要在两张表之间建立多对多关系,您需要使用连接表。 在这种情况下,连接表只包含两列——外键。 IntelliJ IDEA 能够自动检测这样的表,并识别两个表之间的关系基数,这两个表的 ids 在连接表中表示为外键,如 @ManyToMany

CREATE TABLE users ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, last_name VARCHAR(255), first_name VARCHAR(255), CONSTRAINT pk_users PRIMARY KEY (id) ); CREATE TABLE profiles ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, join_date date, status VARCHAR(255), bio VARCHAR(255), CONSTRAINT pk_profiles PRIMARY KEY (id) ); CREATE TABLE profiles_users ( profile_id BIGINT NOT NULL, users_id BIGINT NOT NULL, CONSTRAINT pk_profiles_users PRIMARY KEY (profile_id, users_id) ); ALTER TABLE profiles_users ADD CONSTRAINT fk_prouse_on_profile FOREIGN KEY (profile_id) REFERENCES profiles (id); ALTER TABLE profiles_users ADD CONSTRAINT fk_prouse_on_user FOREIGN KEY (users_id) REFERENCES users (id);
many-to-many-diagram
many-to-many-wizard

如果任何实体中不存在此关联,IntelliJ IDEA 将在调用反向工程操作的实体中生成该关联。

@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @ManyToMany @JoinTable(name = "profiles_users", joinColumns = @JoinColumn(name = "users_id"), inverseJoinColumns = @JoinColumn(name = "profile_id")) private Set<Profile> profiles = new LinkedHashSet<>(); //... }

如果此关联已经存在于其中一个实体中,那么 IntelliJ IDEA 将生成带有 @ManyToMany 属性和 mappedBy 参数的属性。

@Entity @Table(name = "profiles") public class Profile { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @ManyToMany(mappedBy = "profiles") private Set<User> users = new LinkedHashSet<>(); //... }

JPA 逆向工程设置

JPA 逆向工程 设置允许配置 IntelliJ IDEA 在逆向工程期间如何将数据库表和列映射为实体及实体字段。

JPA 逆向工程设置

基础设置

条目

描述

为 @OneToOne 和 @ManyToOne 关联使用 FetchType.LAZY

获取策略 设置为 FetchType.LAZY ,用于 @OneToOne@ManyToOne 关联。

使用验证注解(NotNull、Size 等…)

使用根据列元数据推断的 Jakarta Bean Validation 约束 (如 @NotNull@Size )为实体字段添加注解。

将表名转换为单数形式以生成类名

为实体类命名时,将复数表名称转换为单数形式。

例如,如果表名称为 users ,生成的实体类名称将为 用户 ,而不是 Users

将 ORM 引用替换为基本类型特性

将外键列映射为基础特性,而不是关系字段。

例如,对于名称为 customer_id 的外键列,将会生成 Long customerId 特性,而不是 @ManyToOne Customer customer 关系字段。

表和列评论。

表和列评论。 设置允许您选择如何处理表和列的注释:

  • @Comment 注解 :将其插入 Hibernate @Comment 注解中。

  • Java 文档 :将其插入 Javadoc 注释

  • 忽略 :完全不要插入到编码中。

命名规则

命名规则 设置允许您配置如何将表和列名转换为实体类和字段的名称。 当数据库遵循特定命名约定并且不希望其延续到生成的编码时(如前缀或后缀),此设置非常有用。

您可以选择以下策略之一:

  • 配置 :配置与前缀和后缀相关的设置:

条目

描述

表名中要跳过的前缀

指定在为实体类命名时应从表名称中去除哪些前缀。

例如,若在该字段中输入 sys_ ,并且表名称为 sys_users ,则生成的实体类名称为 用户 ,而不是 SysUser

如需输入多个值,用逗号分隔。

列名中要跳过的前缀

指定在为实体字段命名时应从列名称中去除哪些前缀。

如需输入多个值,用逗号分隔。

表名中要跳过的后缀

指定在为实体类命名时应从表名称中去除哪些后缀。

如需输入多个值,用逗号分隔。

列名中要跳过的后缀

指定在为实体字段命名时应从列名称中去除哪些后缀。

如需输入多个值,用逗号分隔。

保留关键字字段后缀

如遇与 保留 Java 关键字 冲突时,请指定应添加到实体字段名称的后缀。

例如,如果将该后缀设置为 Field 并且某列名称为 class ,则生成的实体字段名称为 classField

  • 算法 :用 Java 编写自定义命名逻辑。 选择此选项后,会显示代码编辑器。 其中包含可根据数据库命名约定调整的方法存根。

映射类型

映射类型 设置允许您重写默认的 SQL 到 Java 类型映射。 可根据需要将 SQL 类型映射为 Java 特性类型、JPA 特性转换器或 Hibernate 自定义类型。 当应用程序需处理特定数据库类型、加密数据或支持使用不同 SQL 类型的多种数据库管理系统时,此设置十分有用。

可为以下数据库管理系统重写类型映射:

下方视频演示如何重写类型映射并使用 Hibernate @JavaType 注解:

2026年 7月 14日