Spring Data JPA DTO

Existem algumas informações que mesmo estando presente no model não devem ser trafegadas via REST. Como senha criptografada de usuário e etc. Além disso podem haver situações em que é necessário disponibilizar várias inforamções de models diferentes em um único endpoint. Dessa forma, ao invés de fazer várias requisições para recuperar essas informações, bastaria uma única requisição para obter todas as informações necessárias. 

Para resolver problemas desse tipo, é bastante comum o uso de DTO (Data Transfer Object) em projetos beckend. DTOs são objetos muito parecidos com models em que eu posso suprimir ou acrestentar informações que serão entregues pelos endpoints.

A ideia é muito simples. Mas pode gerar muito trabalho chato e desnecessário criando métodos para converter um objeto model(Entity) em DTO e DTO em model sempre que form entregar um DTO ou receber um DTO e converter para model que quiser persistir na base de dados.

Para resolver esse problema vamo utilizar uma biblioteca chamada ModelMapper que vai facilitar bastante esse mapeamento de model para DTO e vice-versa.

Como de costume, vamos utilizar o projeto criado nesse post onde temos um endpoint que entrega um model(Entity) Product. Vamos criar um DTO chamando-o de ProductDTO.

Nesse DTO vou suprimir o atributo categories e usar a anotação @Data do lombok para suprimir os getters e setters.

 package com.br.davifelipe.springjwt.dto;
import java.math.BigDecimal;
import lombok.Data;
@Data
 public class ProductDTO {
     
     private Integer id;
     
     private String name;
     
     private BigDecimal price;
 }
 

Vamos adicionar a dependência DataMapper no pom.xml

         <dependency>
           <groupId>org.modelmapper</groupId>
           <artifactId>modelmapper</artifactId>
           <version>2.3.0</version>
         </dependency>

E em seguida alterar o ProductResoruce para retornar o objeto DTO ao invés do model

 package com.br.davifelipe.springjwt.resources;
import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
import org.modelmapper.ModelMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
import com.br.davifelipe.springjwt.dto.ProductDTO;
 import com.br.davifelipe.springjwt.model.Product;
 import com.br.davifelipe.springjwt.services.ProductService;
@RestController
 @RequestMapping("/products")
 public class ProductResoruce {
     
     @Autowired
     private ProductService service;
     
     @GetMapping("/find-by-id/{id}")
     public ResponseEntity<?> findById(@PathVariable(value="id") String id) {
         
         ModelMapper modelMapper = new ModelMapper();
         
         Product product = service.findByid(Integer.parseInt(id));
         
         ProductDTO productDTO = modelMapper.map(product,ProductDTO.class);
         
         return ResponseEntity.ok().body(productDTO);
     }
     
     @GetMapping("/test")
     public List<Product> test() {
         
         BigDecimal price = new BigDecimal(4.5);
         Product mouse = new Product(1, "Mouse", price);
         
         List<Product> lista = new ArrayList<Product>();
         lista.add(mouse);
         
         return lista;
     }
 }
 

Vamos executar o projeto e inserir um registro de teste pelo h2 console 

 INSERT INTO PRODUCT (NAME,PRICE) VALUES ('Mouse',4.5);
  INSERT INTO CATEGORY (NAME) VALUES ('Devices');
  INSERT INTO PRODUCT_CATEGORY (PRODUCT_ID,CATEGORY_ID) VALUES (1,1);
  SELECT * FROM PRODUCT_CATEGORY;

Imagem

https://github.com/davifelipems/spring-backend-template/tree/dto

Agora vamos acesar o endpoint pelo navegador e conferir se é entregue o objeto DTO sem a categoria

Imagem

Comentários

 

Quem Sou

Graduado em ADS (Análise e desenvolvimento de sistemas).

Não sou "devoto" de nenhuma linguagem de programação. Procuro aproveitar o melhor de cada uma de acordo com a necessidade do projeto. Prezo por uma arquitetura bem feita, código limpo, puro e simples!