IntelliJ IDEA 2026.2 Help

Reverse Engineering

Reverse engineering is the process of scaffolding JPA entity classes based on a database schema.

Generate entities from a database

  1. Make sure IntelliJ IDEA is connected to your database.

  2. Open the Database tool window, right-click the database, and select Database icon with a blue table Create JPA Entities from DB….

    Create JPA Entities from DB action
  3. In the JPA Entities from DB dialog that opens, configure the entity mappings and click OK.

Reverse Engineering Columns

Some developers prefer the DB-first application development approach. First, they add columns directly to the database and then update the JPA model. IntelliJ IDEA can automate this process.

Generate entity attributes from a database

  1. Make sure IntelliJ IDEA is connected to your database.

  2. Open the Database tool window, right-click a table, and select Database icon with a blue table Create Entity Attributes from DB….

    Create Entity Attributes from DB action
    • Alternatively, open the Persistence tool window, right-click an entity, and select Plus icon New | Database icon with a blue table Entity Attributes from DB.

  3. In the JPA Entities from DB dialog that opens, configure the entity mappings and click OK.

Smart References Detection

IntelliJ IDEA deeply understands your model. In certain cases, it's able to properly detect cardinality: @OneToOne, @OneToMany, @ManyToOne, @ManyToMany. The coolest thing is that IntelliJ IDEA can show references even when there are no corresponding columns in the current table.

Let's look more closely at each of these cases.

@OneToOne

There are two situations where we can confidently assume the cardinality of the relation as @OneToOne:

  1. Table has a column with the unique constraint that refers to the primary key of another table

  2. Primary key of the table is a foreign key

Case 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 will generate a @OneToOne association with a @JoinColumn annotation in the User entity, and a @OneToOne association with a mappedBy parameter in the Profile entity:

@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; }

Case №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

Since @Id should not be a persistence entity, IntelliJ IDEA will generate:

  • id attribute of a basic type and mark it with @Id annotation

  • users @OneToOne association and mark it with @MapsId annotation

@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

If a table has the column that refers to the primary key of another table, it is most likely a @ManyToOne association. But you are also able to change cardinality to @OneToOne if required. So, depending on which table you call the reverse engineering action, IntelliJ IDEA will detect mapping type as @OneToMany or @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 will generate the following code:

@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

To establish a many-to-many relationship between two tables, you need to use a junction table. The junction table, in this case, contains only two columns - foreign keys. IntelliJ IDEA can automatically detect such a table and identify the relation cardinality between the two tables whose ids are represented as foreign keys in the junction table as @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

If this association does not exist in any of the entities, IntelliJ IDEA will generate it in the entity for which the reverse engineering action was called.

@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<>(); //... }

If this association already exists in one of the entities, then IntelliJ IDEA will generate the @ManyToMany attribute with the mappedBy parameter.

@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<>(); //... }

Video tutorials

The following videos demonstrate how to reverse engineer a database schema when the mapping requires some additional configuration.

Reverse engineer a JPA entity and make it inherit from a parent class

IntelliJ IDEA offers the ability to define a parent entity by selecting a class annotated with @MappedSuperclass from the Parent drop-down box. This allows the generated entities to extend from the parent class and automatically inherit all attributes that have the same name and type.

In cases where the column name in the @MappedSuperclass doesn't match the child entity's table, we can still inherit the attribute using the @AttributeOverride annotation. By simply selecting the attribute name and choosing the one to override, IntelliJ IDEA assists in managing the inheritance.

Inheriting an attribute in the JPA Entities from DB dialog

During entity generation, IntelliJ IDEA alerts us if any inherited attributes from the @MappedSuperclass are missing in the database. To align the model with the database, access the Generate DDL by Entities action in the JPA Structure menu and select the Existing DB update option.

Map a database-specific column type to an entity attribute

For some SQL types, there is no exact match to Java classes. In this case, IntelliJ IDEA does not set the type to prevent generating non-working code. You will need to choose the attribute type yourself. You can also configure default type mappings for each DBMS in the Reference: JPA Reverse Engineering settings.

If you have the HibernateTypes library in your project dependencies list, IntelliJ IDEA can automatically suggest suitable types from the library for the unsupported SQL types during reverse engineering:

Map database views to entities

IntelliJ IDEA follows all best practices providing the most efficient mapping for DB views while reverse engineering:

  1. As DB views do not have a primary key, IntelliJ IDEA allows you to select a field or a set of fields to use as the identifier for the target entity.

  2. Most DB views are immutable. So, IntelliJ IDEA adds @Immutable annotation to the entity and generates getters only. This helps to improve application performance.

  3. IntelliJ IDEA generates only a no-arg protected constructor for entities that are mapped to a DB view, as per JPA specifications, which prevents developers from creating a new instance of such entities in the business logic code.

Reference: Entities from DB dialog

The JPA Entities from DB dialog lets you map your database tables and views to JPA or Spring Data JPA entities.

JPA Entities from DB dialog

The JDBC Entities from DB dialog lets you map your database tables to Spring Data JDBC entities.

JDBC Entities from DB dialog

General options

The top part of the dialog displays options that apply to all generated entity classes:

Item

Description

DB connection

Select which database schema you want to reverse engineer.

You need to select an existing data source from the Database tool window or create a new one by clicking .

Source root

Select a source root where the generated entity classes should be saved.

Options

Select which additional data to include in the generated entity classes:

Target package

Select a package where the generated entity classes should be saved.

Other settings Arrow pointing down

Open JPA Reverse Engineering settings.

Language

Select whether entity classes should be generated in Java or Kotlin.

The top part of the dialog displays options that apply to all generated entity classes:

Item

Description

DB connection

Select which database schema you want to reverse engineer.

You need to select an existing data source from the Database tool window or create a new one by clicking .

Source root

Select a source root where the generated entity classes should be saved.

Options

Select which additional data to include in the generated entity classes:

Target package

Select a package where the generated entity classes should be saved.

Language

Select whether entity classes should be generated in Java or Kotlin.

Entity mapping options

The bottom-left part of the dialog lists tables and views from the selected database, grouped by type and current mapping status:

  • Mapped Relations: tables and views already mapped to entities. Items that are not fully mapped are labeled with unmapped columns.

  • Tables: tables not mapped to any entities.

  • Views: views not mapped to any entities.

When you select a table, view, or relation, the bottom-right part of the dialog lists its mappable elements, also grouped by status:

  • Mapped Columns: columns already mapped to entity attributes.

  • Columns: columns not mapped to any entity attributes.

  • References: foreign keys in other tables that point to this table and are not mapped to any attributes in this table's entity.

For each mappable item, the dialog displays the following options:

Item

Description

Class name

Specify the name of the generated entity class.

IntelliJ IDEA fills this value automatically based on the table name and the JPA Reverse Engineering settings.

Parent

Select a mapped superclass that will be the parent for the generated entity class.

ID generation

Select an ID generation strategy for primary keys:

  • NONE: no automated strategy; the application must assign the ID before the entity is persisted.

  • SEQUENCE: the ID is generated by the selected database sequence and assigned by the persistence provider when the entity is persisted (before the INSERT statement).

  • IDENTITY: the ID is generated and assigned by the database using an auto-increment, serial, or identity column when the entity is persisted (during the INSERT statement).

  • UUID: the ID is generated and assigned by the persistence provider when the entity is persisted (before the INSERT statement).

Learn more about ID generation strategies from official Hibernate documentation.

Id columns

Select which columns should be treated as primary key columns.

Column/Reference Name

Read-only names of columns in the selected table or view and references to it in other tables.

Use the checkboxes to select which columns and references to reverse engineer.

Attribute

Specify names for the generated entity fields.

IntelliJ IDEA fills in these values automatically based on the column name and, if applicable, the JPA Reverse Engineering settings.

If you specified a parent class, you can decide for each matching column whether to inherit its attribute from the parent or generate a new one.

Name attribute with a drop-down list showing options to inherit it from parent or create a new attribute

If an inherited attribute is not an exact match, the entity will use an @AttributeOverride annotation.

Mapping Type

Select how to map the column or reference to an entity attribute.

For descriptions of all available values, refer to Available mapping types.

Attribute/Converter/Hibernate Type

Select which attribute types, JPA attribute converters, or Hibernate custom types to use for the generated entity fields.

The bottom-left part of the dialog lists tables from the selected database, grouped by type and current mapping status:

  • Mapped Relations: tables already mapped to entities. Items that are not fully mapped are labeled with unmapped columns.

  • Tables: tables not mapped to any entities.

When you select a table or relation, the bottom-right part of the dialog lists its mappable elements, also grouped by status:

  • Mapped Columns: columns already mapped to entity attributes.

  • Columns: columns not mapped to any entity attributes.

  • References: foreign keys in other tables that point to this table and are not mapped to any attributes in this table's entity.

For each mappable item, the dialog displays the following options:

Item

Description

Class name

Specify the name of the generated entity class.

IntelliJ IDEA fills this value automatically based on the table name and the JPA Reverse Engineering settings.

ID generation

Select an ID generation strategy for primary keys:

  • NONE: no automated strategy; the ID is generated and assigned by the database using an auto-increment, serial, or identity column when the entity is saved (during the INSERT statement).

  • SEQUENCE: the ID is generated by the selected database sequence and assigned by Spring Data JDBC when the entity is saved (before the INSERT statement).

Id columns

Select which columns should be treated as primary key columns.

Column/Reference Name

Read-only names of columns in the selected table and references to it in other tables.

Use the checkboxes to select which columns and references to reverse engineer.

Attribute

Specify names for the generated entity fields.

IntelliJ IDEA fills in these values automatically based on the column name and, if applicable, the JPA Reverse Engineering settings.

Mapping Type

Select how to map the column or reference to an entity attribute.

For descriptions of all available values, refer to Available mapping types.

Attribute Type

Select which attribute types to use for the generated entity fields.

Available mapping types

The Mapping Type drop-down list lets you select how to map a column or reference to an entity attribute during reverse engineering. The available values depend on whether the item represents ordinary data, a database key, or a reference from another table.

Ordinary columns

Value

Description

Code example

Basic

Map the column to a field of a basic type.

@Column(name = "status", nullable = false, length = 20) private String status;

Enum

Map the column to a separate enum class and then reference it using the @Enumerated annotation.

Book.java @Enumerated(EnumType.STRING) @Column(name = "status", nullable = false, length = 20) private StatusType status; StatusType.java public enum StatusType { }

TODO

Map the column to a field of a basic type, but wrap it in a TODO comment.

You can invoke an action from the TODO comment by placing the caret at the action and pressing Ctrl+B.

/* TODO [Reverse Engineering] create field to map the 'status' column Available actions: Uncomment as is | Remove column mapping @Column(name = "status", nullable = false, length = 20) private java.lang.String status; */

Primary keys

Value

Description

Code example

Basic

Map the column to a field of a basic type and annotate it with @Id.

@Id @Column(name = "isbn", nullable = false, length = 13) private String isbn;

Composite keys

Value

Description

Code example

EmbeddedId

Map the column to a separate embeddable class and then reference it using the @EmbeddedId annotation.

BookAuthor.java @EmbeddedId private BookAuthorId id; BookAuthorId.java @Embeddable public class BookAuthorId implements Serializable { @Serial private static final long serialVersionUID = -8507207156423735624L; @Column(name = "book_isbn", nullable = false, length = 13) private String bookIsbn; @Column(name = "author_id", nullable = false) private Long authorId; }

IdClass

Map the column to a separate class and then reference it using the @IdClass annotation and @Id annotations.

BookAuthor.java @IdClass(BookAuthorId.class) public class BookAuthor { @Id @Column(name = "book_isbn", nullable = false, length = 13) private String bookIsbn; @Id @Column(name = "author_id", nullable = false) private Long authorId; } BookAuthorId.java public class BookAuthorId implements Serializable { private String bookIsbn; private Long authorId; }

Foreign keys

Value

Description

Code example

Basic

Map the column to a field of a basic type.

@Column(name = "publisher_id") private Long publisher;

ManyToOne

Map the column to a reference field with a @ManyToOne annotation.

@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "publisher_id") private Publisher publisher;

OneToOne

Map the column to a reference field with a @OneToOne annotation.

@OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "publisher_id") private Publisher publisher;

TODO

Map the column to a reference field with a relationship annotation, but wrap it in a TODO comment.

You can invoke an action from the TODO comment by placing the caret at the action and pressing Ctrl+B.

/* TODO [Reverse Engineering] create field to map the 'publisher_id' column Available actions: Uncomment as is | Remove column mapping @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "publisher_id") private Publisher publisher; */

References in other tables

Value

Description

Code example

ManyToMany

Map the reference to a set and annotate it with @ManyToMany and @JoinTable annotations.

@ManyToMany @JoinTable(name = "book_authors", joinColumns = {@JoinColumn(name = "book_isbn")}, inverseJoinColumns = {@JoinColumn(name = "author_id")}) private Set<Author> authors = new LinkedHashSet<>();

OneToMany

Map the reference to a set and point to its foreign key attribute in the @OneToMany annotation.

@OneToMany(mappedBy = "bookIsbn") private Set<Review> reviews = new LinkedHashSet<>();

OneToOne

Map the reference to a single field and point to its foreign key attribute in the @OneToOne annotation.

@OneToOne(mappedBy = "bookIsbn") private Review reviews;

The Mapping Type drop-down list lets you select how to map a column or reference to an entity attribute during reverse engineering. The available values depend on whether the item represents ordinary data, a database key, or a reference from another table.

Ordinary columns

Value

Description

Code example

Basic

Map the column to a field of a basic type.

private String status = "";

Enum

Map the column to a separate enum class and then reference it.

Book.java @Nullable private StatusType status; StatusType.java public enum StatusType { }

TODO

Map the column to a field of a basic type, but wrap it in a TODO comment.

You can invoke an action from the TODO comment by placing the caret at the action and pressing Ctrl+B.

/* TODO [Reverse Engineering] create field to map the 'status' column Available actions: Uncomment as is | Remove column mapping private java.lang.String status = ""; */

Primary keys

Value

Description

Code example

Basic

Map the column to a field of a basic type and annotate it with @Id.

@Id private String isbn = "";

Composite keys

Value

Description

Code example

EmbeddedId

Map the column to a separate embeddable class and then reference it.

BookAuthor.java @Nullable @Id @Embedded.Nullable private BookAuthorId id; BookAuthorId.java @NullMarked public class BookAuthorId { private String bookIsbn = ""; private Long authorId = 0L; }

Foreign keys

Value

Description

Code example

Basic

Map the column to a field of a basic type.

@Nullable @Column("publisher_id") private Long publisher;

Reference

Map the column to an AggregateReference field.

@Nullable @Column("publisher_id") private AggregateReference<Publisher, Long> publisher;

TODO

Map the column to an AggregateReference field, but wrap it in a TODO comment.

You can invoke an action from the TODO comment by placing the caret at the action and pressing Ctrl+B.

/* TODO [Reverse Engineering] create field to map the 'publisher_id' column Available actions: Uncomment as is | Remove column mapping @Nullable @Column("publisher_id") private AggregateReference<Publisher, Long> publisher; */

References in other tables

Value

Description

Code example

Set

Map the reference to a set and point to its foreign key column in the @MappedCollection annotation.

@Nullable @MappedCollection(idColumn = "book_isbn") private Set<Review> reviews;

Single

Map the reference to a single field and point to its foreign key column in the @MappedCollection annotation.

@Nullable @MappedCollection(idColumn = "book_isbn") private Review reviews;

Reference: JPA Reverse Engineering settings

The JPA Reverse Engineering settings let you configure how IntelliJ IDEA should map database tables and columns into entities and entity fields during reverse engineering.

JPA Reverse Engineering settings

Base settings

Item

Description

Use FetchType.LAZY for @OneToOne and @ManyToOne associations

Set the fetching strategy to FetchType.LAZY for @OneToOne and @ManyToOne associations.

Use validation annotations (NotNull, Size, etc…)

Annotate entity fields with Jakarta Bean Validation constraints (such as @NotNull or @Size) inferred from column metadata.

Convert the table name to a singular form to generate the class name

When naming entity classes, convert plural table names to their singular form.

For example, if a table is named users, the generated entity class will be named User instead of Users.

Replace ORM references with basic type attributes

Map foreign key columns as basic attributes instead of relationship fields.

For example, for a foreign key column named customer_id, this will generate a Long customerId attribute instead of a @ManyToOne Customer customer relationship field.

Table & column comments

The Table & column comments settings let you select what to do with comments from tables and columns:

  • @Comment annotation: insert them into Hibernate @Comment annotations.

  • Java Doc: insert them into Javadoc comments.

  • Ignore: do not insert them into the code at all.

Naming rules

The Naming Rules settings let you configure how table and column names should be converted into the names of entity classes and fields. This is useful when your database follows specific naming conventions that you do not want to carry over to the generated code, such as prefixes or suffixes.

You can select one of the following strategies:

  • Configs: configure settings related to prefixes and suffixes:

Item

Description

Prefixes to skip in table name

Specify which prefixes should be stripped from table names when naming entity classes.

For example, if you enter sys_ in this field and a table is named sys_users, the generated entity class will be named User instead of SysUser.

If you want to enter multiple values, separate them with commas.

Prefixes to skip in column name

Specify which prefixes should be stripped from column names when naming entity fields.

If you want to enter multiple values, separate them with commas.

Suffixes to skip in table name

Specify which suffixes should be stripped from table names when naming entity classes.

If you want to enter multiple values, separate them with commas.

Suffixes to skip in column name

Specify which suffixes should be stripped from column names when naming entity fields.

If you want to enter multiple values, separate them with commas.

Reserved keyword field suffix

Specify which suffix should be appended to the entity field name if it conflicts with a reserved Java keyword.

For example, if you set this suffix to Field and a column is named class, the generated entity field will be named classField.

  • Algorithm: write custom naming logic in Java. If you select this option, a code editor appears. It includes method stubs that you can adapt to your database's naming conventions.

Mapping types

The Mapping Types settings let you override the default SQL-to-Java type mappings. Depending on your needs, you can map an SQL type to a Java attribute type, a JPA attribute converter, or a Hibernate custom type. This is useful when your application will work with database-specific types, encrypt data, or support multiple database management systems that use different SQL types for the same kind of data.

You can override the type mappings for the following database management systems:

The following video demonstrates how to override a type mapping to use the Hibernate @JavaType annotation:

13 August 2026