1
resposta

Topico TOP! Comprar dois objetos e sobrescrever valores dinamicamente para atualizar

Galera, dentro de um processo de atualização de valores (atributos) de objetos, temos aquele passo a passo mais comum:

Digamos que eu recuperei um determinado objeto A do banco de dados e agora recebi um segundo objeto do mesmo tipo (vou chamar de B) para atualizar algumas informações desse objeto A.

Basicamente pegamos os atributos do segundo objeto B que queremos atualizar (pode ser até um DTO com menos atributos que o A) e "settamos" no objeto A.

Por último salvamos o objeto A e pronto. Ok?

Um problema que vejo nisso é quando temos por exemplo um objeto A com uns 20 atributos e queremos atualizar 10 deles, caramba fazer 10 set e get é um pé no saco e o código fica grande, imagina objetos com mais atributos ainda...

Outro porém agora: Mas e se não sabemos quais valores estão vindo no segundo objeto? como vamos pegar e settar as informações ? fazendo um monte de if com um monte de set?

Durante muito tempo, eu usei em alguns casos um método para sobrescrever esses atributos dinamicamente, sem precisar fazer o set e get de cada um dos atributos: Vejam um exemplo abaixo:

Categoria.java:

@ToString
public class Categoria {

    @Getter @Setter
    private String nome;

    @Getter @Setter
    private String descricao;

    @Getter @Setter
    private String responsavel;

    @Getter @Setter
    private Integer anoValidade;

    @Getter @Setter
    private String situacao;

    public Categoria() {}

    public void updateValues(Categoria categoria) {

        if(categoria.getNome()!=null) {
            this.nome = categoria.getNome();
        }

        if(categoria.getDescricao()!=null) {
            this.descricao = categoria.getDescricao();
        }

        if(categoria.getResponsavel()!=null) {
            this.responsavel = categoria.getResponsavel();
        }

        if(categoria.getAnoValidade()!=(null)) {
            this.anoValidade = categoria.getAnoValidade();
        }

        if(categoria.getSituacao()!=null) {
            this.situacao = categoria.getSituacao();
        }
    }

Agora o exemplo da execução:

public class TesteObjetos {

    public static void main(String[] args) {

        /*
         * Vamos supor que esse objeto categoria já
         * veio do BD com o valores já populados,
         * (como se não tivessem os setters)
         */
        Categoria categoriaBD = new Categoria();
        categoriaBD.setNome("Eletrônicos");
        categoriaBD.setDescricao("Produtos Eletrônicos");
        categoriaBD.setResponsavel("José");
        categoriaBD.setAnoValidade(2022);
        categoriaBD.setSituacao("Ativo");
        System.out.println(categoriaBD);


        /*
         * Agora vamos supor que esta outra categoria
         * represente um objeto que recebemos para 
         * atualizar apenas 3 atributos, que também já 
         * vieram populados(como se não tivesse os setters)
         */
        Categoria dadosRecebidos = new Categoria();
        categoriaBD.setResponsavel("João");
        dadosRecebidos.setNome("Eletrônicos e Computadores");
        dadosRecebidos.setDescricao("Produtos Eletrônicos e de Informática");

        //Por fim sobrescrevo os dados e confirma na impressão
        categoriaBD.updateValues(dadosRecebidos);
        System.out.println(categoriaBD);

        //Aqui eu salvaria o objeto de volta no banco de dados (update).

    }

}

Tudo funciona beleza! Porém, vejam que o meu método que compara se tem valor ou não para sobrescrever acaba ficando muito grande, isso porque estamos falando de uma classe com apenas 5 atributos, imagina uma classe com 20, sei lá...rsss

Por fim quero deixar minha pergunta..rsss Existe alguma maneira mais elegante de fazer isso? Comparar dois objetos e sobrescrever dinamicamente os atributos?

1 resposta

Olá Ailton,

Boa questão, e sim tem solução para isso, se procurar por Mapper vais encontrar várias tipos no mercado. Basicamente a ideia do mapper é fazer este set baseado nos nomes do campos, ou através de notações.

Um dica é MapStruct, segue um exemplo:

<dependency>
   <groupId>org.mapstruct</groupId>
   <artifactId>mapstruct</artifactId>
   <version>1.1.0.Final</version>
   <scope>compile</scope>
</dependency>

CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
CarDto carDto = CarMapper.INSTANCE.carToCarDto(car);

No exemplo é mapeado o objeyo car para carDto.