DTO Generator

Introduction

DTO (data transfer object) is an object that carries data between processes. DTOs for JPA entities generally contain a subset of entity attributes. For example, if you need to expose only a few of the entity attributes via REST API, you can map entities to DTOs with those attributes and serialize only them. Basically, DTOs allow you to decouple presentation/business logic layer from the data access layer.

JPA Buddy offers DTO generation from JPA entities via visual designer:

Mutability

By default, JPA Buddy generates immutable DTOs – all the fields are final, and there are no setters for them. To generate DTOs with simple private fields, setters for them, and no-args constructor, check the Mutable box.
Also, for mutable DTOs, you can define whether to use fluent setters or not. Such setters will return this instead of void. It can be helpful if you want to chain multiple method calls.

Inner DTOs for associations

Entities can reference other entities via associations, and JPA Buddy allows you to generate DTOs for the referenced entities from the same window. Just check the referenced entity in the tree, choose the DTO type and pick the required fields.

Let’s look at the available DTO types:

  • New Class – a new class will be created in a separate file.
  • New Nested Class – a new public static nested class will be created.
  • Existing Class – you can select a DTO class that already exists in the project.
  • Flat – all inner class fields will be top-class fields. Their names will consist of the inner class name + fields names.

Java Records Support

If you use SDK version 16 and higher in your project, then JPA Buddy will provide an additional "Java Record" checkbox in the "New DTO" wizard. To check the SDK version of the project, open File -> Project Structure...

Generate Entities from POJOs

JPA Buddy provides Entity from POJO action that helps to generate a JPA entity from any java/kotlin class. This feature may be helpful if you develop your application following the API-first approach: define DTOs for the API first and implement the data model later.

The most remarkable thing about JPA Buddy is that it even detects the relationship's cardinality and allows to generate related entities or select existing ones:

Generate DTOs from any Java/Kotlin classes

Nowadays, the DTO pattern is widely used in software development. It is not only used with JPA entities, but also with regular POJO classes. With JPA Buddy, you are not restricted to using DTOs with just JPA entities. You can create DTOs from any Java or Kotlin class, which gives you more flexibility and control over your code. For example, check out how easy you can use JPA Buddy with MongoDB documents:

MapStruct Mappers

MapStruct is a code generator that greatly simplifies the implementation of mappings. The "Mapper class" field appears in the "New DTO" window if your project contains the corresponding dependency. You can select an existing Mapper or create a new one.

JPA Buddy analyzes MapStruct mappers and can define which DTO is associated with which entity. Thanks to this, you can see the DTOs in the corresponding section in the JPA Structure and navigate between entity and DTOs through gutter icons.

Mapping Methods

Also, JPA Buddy can help if you prefer to have a single big mapper interface with methods for all entities. In this case, use IntelliJ IDEA "Generate Menu" (Cmd+N/Alt+Insert) in the open mapper class and create methods for any entity.

Generic Mappers Inheritance

MapStruct allows to declare generic mappers:

public interface EntityMapper<D, E> {
    E toEntity(D dto);

    D toDto(E entity);

    List<E> toEntity(List<D> dtoList);

    List<D> toDto(List<E> entityList);
}

Such a mapper is convenient to use as a parent for all other mappers and keep them concise and clean:

@Mapper(componentModel = "spring")
public interface UserMapper extends EntityMapper<UserDTO, User> {}

Still, complex mapping logic can be easily added if required:

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring")
public interface ProjectMapper extends EntityMapper<ProjectDTO, Project> {
    @AfterMapping
    default void linkTasks(@MappingTarget Project project) {
        project.getTasks().forEach(task -> task.setProject(project));
    }
}

JPA Buddy provides a support for generic mappers' inheritance:

Mapper Declaration

JPA Buddy provides flexible settings for mapper declaration. To configure naming patterns or mapping naming strategy for collection, open Tools -> JPA Buddy -> Mapper Declaration:

Keep DTOs in sync with its JPA entity

Refactor attributes

Often DTOs are used at the API controller level, aimed to declare only fields required by the client. That's why DTOs nearly copy the structure of their entities. There are popular frameworks to map entities to DTOs and vice versa: MapStruct and ModelMapper. They auto-map namesake properties. Hence, changing the property name in an entity often leads to the corrupted mapping logic. That's why JPA Buddy helps developers to refactor entity properties along with the related fields in DTOs:

Add attributes

Happens, you have added a new attribute to the entity. Then, some already existing DTOs will also need this field. JPA Buddy allows you to add a new field to all the required DTOs at once.

DTO Declaration Settings

Each project may follow its own conventions for code writing. In the Tools -> JPA Buddy -> DTO Declaration you can configure:

  1. Serializable type.
  2. Class name postfix.
  3. Whether to use Lombok or not.
  4. Name pattern regexp. This option is useful if you use an obligatory naming convention for DTOs. It allows JPA Buddy to associate DTO with its JPA Entity using a DTO name only. To specify a placeholder for the simple class name of the target JPA entity, use the (?<entity>.) pattern. E.g., (?.)Dto means that the MyEntityDto class will be considered as a DTO for MyEntity. The feature is disabled when the field is empty.
  5. Class comment. Defines the comment that will be generated over the DTO class.
  6. Comment link regexp (The feature is disabled when the field is empty). It allows JPA Buddy to associate DTO with its JPA Entity. To specify a placeholder for the target entity FQN (Fully Qualified Name) in a comment use the (?<entity>.*) pattern. So, if the regexp is defined as A DTO for the{@link (?.*)} entity. it will be resolved in the following comment:
// A DTO for the {@link io.jpabuddy.demo.entities.Project} entity.

Convenient Navigation between Entity and its DTOs

As soon as JPA Buddy is able to associate DTO class with the entity:

  • The DTO class will appear in the Dto & Projections section in the JPA Structure tab and in the Editor Toolbar (1)
  • The gutter icon will appear in the DTO to ease the navigation to its entity (2)