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

8 respostas
L

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

8 Respostas

J

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?

L

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!!

J

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ç

L

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=?
J

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 =)

L

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

J

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

L

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!!

Criado 19 de junho de 2011
Ultima resposta 20 de jun. de 2011
Respostas 8
Participantes 2