[PT-BR] Padrão de Projeto: Data Transfer Object
Tags: tutorial, dto, java, padraodeprojeto
Published: 2020-12-28 20:57:57

---
title: [PT-BR] Padrão de Projeto: Data Transfer Object
published: true
description: Entendendo sobre o padrão de projeto Data Transfer Object com Java.
tags: tutorial, dto, java, padraodeprojeto
cover_image: https://images.unsplash.com/photo-1557754897-ca12c5049d83?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80
---

Sempre quando ouvia falar sobre padrão de projeto eu já imaginava alguma implementação ou arquitetura muito complexa para o que eu estava acostumado. Porém, nos últimos tempos, me dei conta que estava trabalhando com um padrão de projeto que facilitava muito a "conversa" entre os sistemas clientes e os sistemas servidores e gostaria de explicá-lo nesse artigo. 

Espero que a compreensão de algo que, para mim, num geral, era super complexo seja mais simples para vocês.

## Data Transfer Object

O Data Transfer Object (DTO), ou conhecido em alguns lugares apenas como Transfer Object (TO), é um padrão em que utilizamos classes que possuem informações que são formadas a partir de uma ou mais entidades (classes cujos atributos são mapeados para os campos de uma tabela em um banco de dados). Essas classes tem o objetivo de simplificar a maneira como um sistema deve conversar com outro em relação à algum processo.

## DTO na prática

O exemplo que demonstrei a seguir leva em consideração um processo de guardar um novo registro `Usuário` na base de dados e a resposta que a nossa API irá retornar.

Nesse exemplo, estarei utilizando uma implementação em Java com [Spring Boot](https://spring.io/projects/spring-boot).

### Classes

Nossa classe UsuarioEntity (responsável por fazer o mapeamento da nossa classe e atributos com a tabela e campos da base de dados):

```java
package com.leonardossev.dtoexemplo.model.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "usuario")
public class UsuarioEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "nome")
    private String nome;

    @Column(name = "email", unique = true)
    private String email;

    @Column(name = "senha")
    private String senha;

    // Getters e Setters...

}

```

Nosso Repository (interface responsável por interagir com a base de dados):

```java
package com.leonardossev.dtoexemplo.repository;

import com.leonardossev.dtoexemplo.model.entity.UsuarioEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UsuarioRepository extends JpaRepository<UsuarioEntity, Long> {
}

```

Nosso Service:

```java
package com.leonardossev.dtoexemplo.service;

import com.leonardossev.dtoexemplo.model.entity.UsuarioEntity;
import com.leonardossev.dtoexemplo.repository.UsuarioRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UsuarioService {

    @Autowired
    private UsuarioRepository usuarioRepository;

    public UsuarioEntity salvarUsuario(UsuarioEntity usuario) {
        return this.usuarioRepository.save(usuario);
    }
}
```

Nosso Controller: 

```java
package com.leonardossev.dtoexemplo.controller;

import com.leonardossev.dtoexemplo.model.entity.UsuarioEntity;
import com.leonardossev.dtoexemplo.service.UsuarioService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(path = "/usuario")
public class UsuarioController {

    @Autowired
    private UsuarioService usuarioService;

    @PostMapping
    public ResponseEntity<UsuarioEntity> salvarUsuario(final @RequestBody UsuarioEntity usuario) {
        return new ResponseEntity<UsuarioEntity>(this.usuarioService.salvarUsuario(usuario), HttpStatus.CREATED);
    }

}

```

### Executando nossa aplicação

Para testar o endpoint responsável por guardar o registro na base, utilizarei o [Insomnia](https://insomnia.rest/).

Lembrando que, se não especificarmos nenhuma porta, ao executar a nossa aplicação, ela estará disponível na porta 8080.

![Requisição POST via Insomnia para localhost:8080/usuario](https://i.imgur.com/qH4duC9.png)

Note que estamos recebendo exatamente as informações que salvamos na nossa base de dados. Mas em uma aplicação real provavelmente não gostaríamos de receber todos os dados dessa forma.

Por exemplo: não iríamos querer que a senha do nosso usuário (sem entrar no mérito de criptografia) estivesse exposta dessa forma.

Outro exemplo: se quiséssemos trazer informações relacionadas ao usuário que não estão exatamente na tabela de usuário.

No nosso caso, o uso de DTO pode nos ajudar a solucionar essa questão de forma a nos permitir a escolher quais dados nós queiramos disponibilizar quando salvarmos um novo usuário.

Vamos adicionar a seguinte classe ao nosso projeto:

```java
package com.leonardossev.dtoexemplo.model.dto;

public class UsuarioDTO {

    private Long id;

    private String nome;

    private String email;

    public UsuarioDTO(Long id, String nome, String email) {
        this.id = id;
        this.nome = nome;
        this.email = email;
    }

    // Getters e setters...

}

```

Vamos também fazer os seguintes ajustes:

- Implementar um método na classe `UsuarioEntity` que irá transformar as informações da classe `UsuarioEntity `para informações da classe `UsuarioDTO`;
- Fazer com que o nosso endpoint retorne um objeto da classe `UsuarioDTO`.

#### Implementando método para transformar informações

Na classe `UsuarioEntity` vamos criar o seguinte método:

```java
    public UsuarioDTO obterUsuarioDTO() {
        return new UsuarioDTO(this.id, this.nome, this.email);
    }

```

#### Alterando retorno do endpoint de salvar usuário

No nosso service, iremos ajustar a implementação do método `salvarUsuario(UsuarioEntity usuario)` para que ele possa retornar um objeto da classe `UsuarioDTO`:

```java
    public UsuarioDTO salvarUsuario(UsuarioEntity usuario) {
        var usuarioSalvo = this.usuarioRepository.save(usuario);

        return usuarioSalvo.obterUsuarioDTO();
    }

```

Além disso, é necessário que façamos ajustes no método do nosso controller:

```java
@PostMapping
    public ResponseEntity<UsuarioDTO> salvarUsuario(final @RequestBody UsuarioEntity usuario) {
        return new ResponseEntity<UsuarioDTO>(this.usuarioService.salvarUsuario(usuario), HttpStatus.CREATED);
    }
```

Dessa forma, quando executamos a aplicação e tentamos salvar um novo usuário, recebemos as seguintes informações:

![Requisição POST via Insomnia para localhost:8080/usuario](https://i.imgur.com/mXQ169d.png)

Perceba que não estamos recebendo a informação da senha do usuário.

## Considerações finais

O repositório com o exemplo do artigo pode ser encontrado [aqui](https://github.com/LeonardoSSev/spring-dto-artigo).

## Referências
https://www.baeldung.com/hibernate-identifiers
https://stackabuse.com/data-transfer-object-pattern-in-java-implementation-and-mapping/

Em caso de dúvidas, estou sempre aberto a sugestões, críticas e ideias! o/