Você já se viu perdido em meio a uma selva de código, tentando converter objetos Java de um tipo para outro? Se a resposta é sim, então você precisa continuar lendo, pois queremos acabar de vez com essa dor de cabeça. Neste artigo, vamos falar sobre o MapStruct, uma ferramenta brilhante que faz da conversão de objetos Java uma tarefa tão fácil quanto tomar uma xícara de café!
O que é MapStruct e o que ele faz?
MapStruct é uma biblioteca Java criada com o propósito de evitar o boilerplate code, que muitas vezes polui nosso código e torna a manutenção complicada. Ela simplifica muito o processo de mapeamento de objetos, pois apenas com interfaces Java e anotações, podemos definir as regras de mapeamento entre as classes e gerar automaticamente o código quando a aplicação é compilada. Assim, você não precisa criar várias classes builders manualmente para construir instâncias dos seus objetos. Isso é muito bom quando você possui muitas entidades na sua aplicação e precisa fazer muitas transformações para DTO’s e vice-versa.
Como utilizar o MapStruct?
Para exemplificar, vamos utilizar um exemplo bem simples e direto ao ponto. Não criaremos um projeto e nem discutiremos sobre frameworks e gerenciadores de dependências, então vamos apenas assumir que temos um projeto fictício com Spring Boot e Maven. Caso não esteja utilizando o Maven em seu projeto, você pode procurar como configurar o MapStruct de acordo com o seu gerenciador de dependências.
No nosso caso, com o Maven, precisamos apenas adicionar a dependência do MapStruct e configurar o maven-compiler-plugin com o processador de anotações do MapStruct no arquivo pom.xml.
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.3.Final</version> <!-- Utilizar a versão mais recente -->
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source> <!-- Troque pela sua versão do Java -->
<target>17</target> <!-- Troque pela sua versão do Java -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.3.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
Agora vamos ao código Java!
Imagine que você tem duas classes, Carro
e CarroDTO
, e quer converter uma instância de Carro
em uma instância de CarroDTO
. Em um mundo sem MapStruct, você provavelmente criaria manualmente uma instância de CarroDTO
setando seus atributos com os valores dos atributos correspondentes no objeto Carro
. Mas veja agora como você pode fazer com o MapStruct.
Criamos nossas duas classes que usaremos como exemplo:
public class Carro {
private String modelo;
private Integer ano;
// outros atributos, construtores, getters e setters
}
public class CarroDTO {
private String modelo;
private Integer ano;
// outros atributos, construtores, getters e setters
}
Agora, criamos uma interface com anotações MapStruct para realizar o mapeamento:
@Mapper
public interface CarroMapper {
CarroMapper INSTANCE = Mappers.getMapper(CarroMapper.class);
CarroDTO toCarroDTO(Carro carro);
}
Por fim, já podemos usar a instância de CarroMapper para fazer o mapeamento, e para isso, vamos apenas criar nosso objeto de origem e chamar nosso mapper.
Carro carro = new Carro();
carro.setModelo("Ferrari 296 GTB");
carro.setAno(2024);
CarroDTO carroDTO = CarroMapper.INSTANCE.toCarroDTO(carro);
Perceba o quanto foi simples converter uma instância de Carro
em uma instância de CarroDTO
sem precisar setar cada atributo manualmente no objeto de destino.
E quando há muitos atributos e objetos aninhados?
Onde o MapStruct realmente brilha é em situações do mundo real, onde temos objetos complexos com muitos atributos e hierarquias. Vamos imaginar uma aplicação de comércio eletrônico onde precisamos converter entidades de pedidos para DTOs de pedidos.
public class Produto {
private Long id;
private String nome;
}
public class Cliente {
private Long id;
private String nome;
private String CPF;
}
public class Pedido {
private Long id;
private List<ItemPedido> itens;
private Cliente cliente;
}
public class ItemPedido {
private Long id;
private Produto produto;
private Integer quantidade;
}
public class PedidoDTO {
private Long id;
private List<ItemPedidoDTO> itens;
private String nomeCliente;
}
public class ItemPedidoDTO {
private Long id;
private String nomeProduto;
private Integer quantidade;
}
Agora, vamos criar nossas interfaces de mapeamento com o MapStruct:
@Mapper(uses = ItemPedidoMapper.class)
public interface PedidoMapper {
PedidoMapper INSTANCE = Mappers.getMapper(PedidoMapper.class);
@Mapping(source = "cliente.nome", target = "nomeCliente")
PedidoDTO toPedidoDTO(Pedido pedido);
}
@Mapper
public interface ItemPedidoMapper {
ItemPedidoMapper INSTANCE = Mappers.getMapper(ItemPedidoMapper.class);
@Mapping(source = "produto.nome", target = "nomeProduto")
ItemPedidoDTO toItemPedidoDTO(ItemPedido itemPedido);
}
Acredito que aqui você já entendeu que agora basta chamar o PedidoMapper
, passando seu objeto Pedido
, e ele irá mapear e retornar um PedidoDTO
com todos os campos setados, inclusive a lista de itens do pedido.
Bem simples, né? Podemos facilmente converter entidades complexas em DTOs, mantendo nosso código limpo e de fácil entendimento. Além disso, estamos trabalhando de forma mais eficiente ao utilizar o Mappers.getMapper()
para criar nossa INSTANCE, pois por baixo dos panos o MapStruct está usando uma abordagem Singleton que cria um ponto único de acesso à implementação do mapper. Ou seja, sempre será utilizada uma única instância para realizar as operações de mapeamento, proporcionando maior eficiência.
Conclusão
Espero que este conteúdo tenha sido útil para você e te ajude a tornar seu desenvolvimento em Java mais simples, limpo e eficiente. Você pode conferir também a documentação oficial, se precisar.
Quer saber mais sobre ferramentas, bibliotecas e outros assuntos relacionados ao desenvolvimento de software? Acesse a nossa página de artigos na categoria Ferramentas. Deixe seus comentários ou entre contato se precisar de algo. Até logo!