1
resposta

[Dúvida] Quando precisamos receber um Multipart em vez de um JSON, como podemos criar o DTO sem setters?

Estou desenvolvendo uma aplicação de agendamento de estadias em hotéis, e a entidade Hotel possui atributos, incluindo um atributo de imagem, que por escolha pessoal, preferi salvar em formato byte[] no banco de dados. Para fazer isso, preciso receber um MediaType do tipo Multipart. No entanto, percebi que ao usar um DTO, ocorria um erro. Quando criei uma classe com métodos setters, a execução ocorreu perfeitamente. Acredito que isso aconteça porque, por debaixo dos panos, a classe é instanciada e depois os valores da requisição são setados. Gostaria de saber se existe outra maneira de receber esses dados ou se posso simplesmente deixar o meu DTO com métodos setters

Imagem que retrata o recebimento do MediaType como Multipart

1 resposta

Olá Artur.

Tudo bem?

Realmente, a imutabilidade dos DTOs é uma prática recomendada para garantir a segurança e a consistência dos dados. No entanto, quando se trata de receber dados via Multipart, o Spring MVC espera que os objetos sejam mutáveis para que ele possa injetar os valores corretamente.

Para resolver isso, você pode usar uma abordagem alternativa que mantém a imutabilidade dos seus DTOs. Uma solução é criar uma classe intermediária que seja mutável e depois converter essa classe em um DTO imutável. Aqui está um exemplo de como você pode fazer isso:

  1. Crie uma classe intermediária mutável:
public class HotelForm {
    private String nome;
    private String endereco;
    private MultipartFile imagem;

    // Getters e Setters
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getEndereco() {
        return endereco;
    }

    public void setEndereco(String endereco) {
        this.endereco = endereco;
    }

    public MultipartFile getImagem() {
        return imagem;
    }

    public void setImagem(MultipartFile imagem) {
        this.imagem = imagem;
    }
}
  1. Crie seu DTO imutável:
public class HotelDto {
    private final String nome;
    private final String endereco;
    private final byte[] imagem;

    public HotelDto(String nome, String endereco, byte[] imagem) {
        this.nome = nome;
        this.endereco = endereco;
        this.imagem = imagem;
    }

    // Getters
    public String getNome() {
        return nome;
    }

    public String getEndereco() {
        return endereco;
    }

    public byte[] getImagem() {
        return imagem;
    }
}
  1. Converta a classe intermediária para o DTO no seu controlador:
@PutMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE, value = "/updateHotel")
public ResponseEntity<HotelDto> updateHotel(@ModelAttribute @Valid HotelForm form) {
    byte[] imagemBytes = null;
    try {
        imagemBytes = form.getImagem().getBytes();
    } catch (IOException e) {
        // Trate a exceção adequadamente
        e.printStackTrace();
    }

    HotelDto dto = new HotelDto(form.getNome(), form.getEndereco(), imagemBytes);
    // Chame o serviço para atualizar o hotel com o DTO
    service.updateHotel(dto);

    return ResponseEntity.ok(dto);
}

Dessa forma, você mantém a imutabilidade dos seus DTOs enquanto ainda permite que o Spring MVC injete os valores via Multipart.

Veja se isso te ajuda, se faz sentido. Qualquer dúvida manda aqui.

Espero ter ajudado e bons estudos!