Retorno de Objetos Duplicados [Hibernate + Criteria] - [RESOLVIDO]

Pessoal Boa Noite! Como estou começando no assunto perdoe-me se falar alguma bobeira…
Seguinte estou com o seguinte senário de testes simples, uma classe que tem duas listas populo a lista e gravo no banco normalmente, busco por id normalmente, porem quando filtro mais de um objeto a lista de retorto deste objeto pesquisado vem duplicada, vou expor abaixo.
Que puder ajudar desde já agradeço, pois não sei se estou erando em mapeamento, criteria ou outra coisa… a todos muito obrigado!!

Classe:


@Entity
@Table(name = "animais")
public class AnimalTO {

	@Id
	@GeneratedValue
	@Column(unique = true)
	private Integer id;

        @CollectionOfElements(fetch = FetchType.EAGER)
	private Set<String> alergias;

	@CollectionOfElements(fetch = FetchType.EAGER)
	private Set<String> doencas;

// gets sets

}

Gravo no Banco 2 Animais com 2 itens em cada lista:


                AnimalTO animalTO = new AnimalTO();
		AnimalDAO animalDAO = new AnimalDAO();

		animalTO.setAlergias(new HashSet<String>());
		animalTO.getAlergias().add("ALERGIA 1");
		animalTO.getAlergias().add("ALERGIA 2");

		animalTO.setDoencas(new HashSet<String>());
		animalTO.getDoencas().add("DOENCA 1");
		animalTO.getDoencas().add("DOENCA 2");

		try {
			animalDAO.saveOrUpdate(animalTO);
		} catch (Exception e) {
			e.printStackTrace();
		}

Grava tudo certo no banco porem quando recupero do banco traz duplicados:

DAO:


public List<AnimalTO> listarTodos(AnimalTO animalTO) throws Exception {
		Session sessao = null;

		List<AnimalTO> lista = new ArrayList<AnimalTO>();
		try {

			sessao = HibernateUtil.getSessionFactory().openSession();

			Criteria criteria = sessao.createCriteria(AnimalTO.class);

			criteria.addOrder(Order.asc("id"));

			lista = (ArrayList<AnimalTO>) criteria.list();
			
		} catch (Exception e) {
                        lista = null;
			e.printStackTrace();
		} finally {
			sessao.close();
		}
		return lista;
	}

Busca:


		try {

			AnimalDAO animalDAO = new AnimalDAO();
			int cont = 0;
			for (AnimalTO to : animalDAO.listarTodos(new AnimalTO())) {
				System.out.println("\n######################## - Indice: " + cont);

				System.out.println("Id animal: " + to.getId());

				System.out.println("\n - Doencas");
				for (String s : to.getDoencas()) {
					System.out.println(s);
				}
				System.out.println("\n - Alergias");
				for (String s : to.getAlergias()) {
					System.out.println(s);
				}

				System.out.println("\n########################");
				cont++;
			}

			System.out.println("Numero de Animais Retornados: " + cont);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	

Rertono da busca:

######################## - Indice: 0
Id animal: 1

 - Doencas
DOENCA 1
DOENCA 2

 - Alergias
ALERGIA 1
ALERGIA 2

########################

######################## - Indice: 1
Id animal: 1

 - Doencas
DOENCA 1
DOENCA 2

 - Alergias
ALERGIA 1
ALERGIA 2

########################

######################## - Indice: 2
Id animal: 1

 - Doencas
DOENCA 1
DOENCA 2

 - Alergias
ALERGIA 1
ALERGIA 2

########################

######################## - Indice: 3
Id animal: 1

 - Doencas
DOENCA 1
DOENCA 2

 - Alergias
ALERGIA 1
ALERGIA 2

########################

######################## - Indice: 4
Id animal: 2

 - Doencas
DOENCA 1
DOENCA 2

 - Alergias
ALERGIA 1
ALERGIA 2

########################

######################## - Indice: 5
Id animal: 2

 - Doencas
DOENCA 1
DOENCA 2

 - Alergias
ALERGIA 1
ALERGIA 2

########################

######################## - Indice: 6
Id animal: 2

 - Doencas
DOENCA 1
DOENCA 2

 - Alergias
ALERGIA 1
ALERGIA 2

########################

######################## - Indice: 7
Id animal: 2

 - Doencas
DOENCA 1
DOENCA 2

 - Alergias
ALERGIA 1
ALERGIA 2

########################
Numero de Animais Retornados: 8

Aparentemente seu código está correto, o único porém é no seu DAO você receber uma instância da classe AnimalTO e não a usar. Mas isso não interfere no funcionamento do seu código. Como está no banco as informações? Estão duplicadas?

Que banco você está usando?

A sim referente ao parametro agora nao utulizo pois esto fazendo testes, depois colocarei as devidas Restrictions e talz, o banco nao tem dados duplicados, tem 2 animais cada um com duas doencas e duas alergias, tipo coloquei o print do id, ai da para ver, uso mysql.
Desde ja’ obrigado pela ajuda amigo!!

Vamos fazer uns testes.

Você colocou uma lista para doenças e alergias certo? Só que você usou uma lista de Strings. Mas assim, não existe a entidade Alergias e Doenças, existe? Como o Hibernate vai salvar então vários registros de alergias se não existe tabela? Chutômetro: Ele deve estar criando um campo na tabela de Animais, chamado Alergia e toda vez que tem uma alergia nova, ele salva outra linha igual, apenas mudando a alergia.

Mas vamos testar como ele salva e como ele faz a consulta, no seu arquivo de configuração do hibernate, acrescente a propriedade show_sql = true. E cola aqui, as querys que o Hibernate criou.

Mas acho que tem haver com a lista de Strings, acho que o ideal, é você criar as entidades de Alergia e de Doença e fazer o relacionamento @OneToMany

Qualquer dúvida, posta ai

Abç

Nao tenho as classes pois sao meramentes dados demonstrativos, o hibernate cria como fosse o oneToMany mesmo um tabela a parte animal_alergia onde tem o id do animal e a descricao da alergia, e o mesmo para doenca.

to ligado o oneToMany, ja tive oportunidade de utiliza-lo…

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "entregaFabrica")
	private Set<ProgramaEntregaFabricaTO> intensDaEntrega;

segue a SQL


Hibernate: select animalto0_.id as id1_1_, animalto0_.id_cliente as id8_1_1_, animalto0_.cor as cor1_1_, animalto0_.dataNascimento as dataNasc3_1_1_, animalto0_.nome as nome1_1_, animalto0_.peso as peso1_1_, animalto0_.porte as porte1_1_, animalto0_.raca as raca1_1_, clienteto1_.id as id2_0_, clienteto1_.cpf as cpf2_0_, clienteto1_.dataCadastro as dataCada3_2_0_, clienteto1_.endereco as endereco2_0_, clienteto1_.nome as nome2_0_, clienteto1_.telefoneCelular as telefone6_2_0_, clienteto1_.telefoneResidencial as telefone7_2_0_ from animais animalto0_ inner join clientes clienteto1_ on animalto0_.id_cliente=clienteto1_.id where animalto0_.id=?

Estranho esse problema, nunca usei essa anotation

Mas achei um link que pode te ajudar

http://pt.w3support.net/index.php?db=so&id=1093153

Parece que o problema é no Fetch.Eager

Dá uma lida ai, e depois posta se resolveu =)

Certo to vendo aqui, cara vo fazer um teste de adaptacao funcional hehhehe
feio hem heh mais veja o que vc acha


			Criteria criteria = sessao.createCriteria(AnimalTO.class);
			
			criteria.setProjection(Projections.distinct(Projections
					.property("id")));
			
			criteria.addOrder(Order.asc("id"));

			lista = (ArrayList<AnimalTO>) criteria.list();

kkk resolveria meu problema hem suahasu

Verdade, resolveria sim. Rs

Aliás, isso é até sugerido no link que te passei. Mas não sei se é o mais performático. Se não causar impacto no banco e acredito que não gerará, é uma solução válida.

PS: Adaptação funcional foi ótima hahahaha

E’ amigo então fico assim por hora

Funcionando:

lista = (ArrayList<AnimalTO>) criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();

Amigo javablue, muito obrigado pela ajuda meu velho se achar mais alguma coisa eu posto aqui!!
Até mais amigo!!

1 curtida