Tenho aqui um método do meu PessoaService chamado listar que deveria iterar pelo repositório de Pessoas e popular um novo ArrayList contendo PessoaDto para requisições GET.
O problema é que quando chamada, esse código altera todos os objetos PessoaDto dentro do array, para a ultima iteração do forEach, e exibe todos os itens repetidos no postman. Porém consultando o banco de dados, os dados estão corretos. Alguém sabe me dizer o que pode estar acontecendo?
é uma classe que herda do JPARepository. Tem métodos próprios.
O print imprime errado também, pois a lista está cheia de objetos com os dados do ultimo objeto. entende?
O método findAll é um dos métodos presentes no SpringDataJPA. O JPA disponibiliza em tempo de execução uma implementação para a interface.
Este é o código do método não implementado:
List<T> findAll();
/**
* Returns all instances of the type {@code T} with the given IDs.
* <p>
* If some or all ids are not found, no entities are returned for these IDs.
* <p>
* Note that the order of elements in the result is not guaranteed.
*
* @param ids must not be {@literal null} nor contain any {@literal null} values.
* @return guaranteed to be not {@literal null}. The size can be equal or less than the number of given
* {@literal ids}.
* @throws IllegalArgumentException in case the given {@link Iterable ids} or one of its items is {@literal null}.
*/
E este é o código do meu PessoaDtoBuilder:
package br.com.dev.domain.model.DTO;
public class PessoaDtoBuilder {
private PessoaDto pessoa = new PessoaDto();
private EnderecoDto endereco = new EnderecoDto();
private static PessoaDtoBuilder instancia = null;
private PessoaDtoBuilder() {
}
public static PessoaDtoBuilder builder() {
if(instancia == null) {
instancia = new PessoaDtoBuilder();
return instancia;
}
return instancia;
}
public PessoaDtoBuilder setNome(String nome) {
pessoa.setNome(nome);
return this;
}
public PessoaDtoBuilder setData(String data) {
pessoa.setDataDeNascimento(data);
return this;
}
public PessoaDtoBuilder setLogradouro(String logradouro) {
endereco.setLogradouro(logradouro);
return this;
}
public PessoaDtoBuilder setCep(String cep) {
endereco.setCep(cep);
return this;
}
public PessoaDtoBuilder setNumero(Integer numero) {
endereco.setNumero(numero);
return this;
}
public PessoaDtoBuilder setCidade(String cidade) {
endereco.setCidade(cidade);
return this;
}
public PessoaDto build() {
pessoa.setEnderecoDto(endereco);
return pessoa;
}
}
O erro estava na minha classe PessoaDtoBuilder. Estava usando o design pattern singleton pra garantir uma única instancia de builder. Só que todos os objetos do ArrayList apontavam pra essa mesma instancia, o que fazia com que na ultima iteração do forEach, o builder recebesse os dados do último objeto de pessoaRepository.findAll(), e por consequência todos os objetos PessoaDto dentro do array que apontavam para a unica instancia de builder.
Então foi só remover esse design pattern como abaixo:
package br.com.dev.domain.model.DTO;
public class PessoaDtoBuilder {
private PessoaDto pessoa = new PessoaDto();
private EnderecoDto endereco = new EnderecoDto();
private static PessoaDtoBuilder instancia = null;
private PessoaDtoBuilder() {
}
public static PessoaDtoBuilder builder() {
// if(instancia == null) {
// instancia = new PessoaDtoBuilder();
// return instancia;
// }
instancia = new PessoaDtoBuilder();
return instancia;
}
...
Não precisas disto private static PessoaDtoBuilder instancia = null; nem do método statico builder, podes simplesmente tornal public o construtor da classe.