Conteúdo do item:
Biblioteca para passar valores de DTOS para os Entities.
Link oficial da biblioteca:
https://mapstruct.org/
Link sobre diferentes bibliotecas e performance:
https://www.baeldung.com/java-performance-mapping-frameworks
Link para mapear campos diferentes
https://mapstruct.org/documentation/stable/api/org/mapstruct/Mappings.html
Link para todas as funções
https://mapstruct.org/documentation/stable/reference/html/
Em muitos projetos temos os mapeamentos da tabela do banco de dados em classes, que chamamos de Entity, porem temos as nossas APIS que recebem ou devolvem informações, para interagir com o nosso Banco de Dados, e nem sempre queremos devolver todas as informações das tabelas, nesses casos criamos os DTOS com as informações que gostaríamos de devolver, e para isso precisamos mapear as informações do Entity para os DTO, onde dão um pequeno trabalho, e podemos fazer o mesmo trabalho com um mapeamento automático utilizando o MapStruct.
Vamos criar uma variável de versão do MapStruct no pom.xml, dentro do properties do projeto, para que possamos utilizar nas Tags de dependências e build. Como estou usando o Lombok eu irei colocar a configuração dele também.
<org.mapstruct.version>1.5.0.Final</org.mapstruct.version>
<org.projectlombok.version>1.18.22</org.projectlombok.version>
Ficando assim
<properties>
<java.version>16</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.target>16</maven.compiler.target>
<maven.compiler.source>16</maven.compiler.source>
<org.mapstruct.version>1.5.0.Final</org.mapstruct.version>
<org.projectlombok.version>1.18.22</org.projectlombok.version>
</properties>
Na sequência dentro da Tag de Build, iremos adicionar um novo plugin de compilação para que durante o build maven execute alguns processos, caso já tenha esse plugin configure somente os annotationProcessorPaths. No exemplo abaixo coloquei para ele reconhecer o Lombok e o MapStruct em conjunto.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<!-- This is needed when using Lombok 1.18.16 and above -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Pegando como exemplo o meu projeto, o BUILD ficou assim:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<!-- This is needed when using Lombok 1.18.16 and above -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
Como criar esses mapeamentos junto ao Spring?
Primeiro criamos uma interface com a anotação @Mapper, nessa interface colocamos todos os métodos de conversão de um Entity específico para um DTO desejado. No caso abaixo quero converter meu BlogEntity para um BlogBaseResponse. Estou utilizando o parâmetro componentModel = "spring" para avisar ao Spring que gostaria de uitilizar o seu gerenciamento de bean.
package br.com.byiorio.api.blog;
import org.mapstruct.Mapper;
@Mapper(componentModel = "spring")
public interface BlogEntityMapper {
BlogBaseResponse toBlogBaseResponse(BlogEntity blogEntity);
}
Depois desse mapeamento podemos fazer um @Autowired para criar uma instância da interface
@Autowired
private BlogEntityMapper blogEntityMapper;
Uma vez criado a variável é só utilizar
@GetMapping(path = "/", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<BlogBaseResponse>> allBlogs() {
Iterable<BlogEntity> lista = blogService.findPubFetchingAll();
if (!lista.iterator().hasNext()) {
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
} else {
List<BlogBaseResponse> listResp = new ArrayList<>();
Iterator<BlogEntity> iter = lista.iterator();
while (iter.hasNext()) {
listResp.add(blogEntityMapper.toBlogBaseResponse(iter.next()));
}
return ResponseEntity.ok(listResp);
}
}
O código foi alterado de:
while (iter.hasNext()) {
BlogEntity item = iter.next();
if (item != null) {
BlogBaseResponse resp = new BlogBaseResponse();
resp.setTitle(item.getTitle());
resp.setId(item.getId());
listResp.add(resp);
}
}
para:
while (iter.hasNext()) {
listResp.add(blogEntityMapper.toBlogBaseResponse(iter.next()));
}
Assista o vídeo para ter uma melhor visão de como utilizar essa biblioteca.
mapper; mapeamento; DTO; bean;lombok;