Olá todos.
Tenho um banco de dados com 3 tabelas: Contact, Contact_phone e Contact_has_Contact_phone, representando uma agenda telefônica simples. São mapeadas pelas classes Contact e ContactPhone. O problema é que, quando faço uma consulta por todos os contatos no banco, a lista retornada pelo Hibernate possui contatos aparecendo mais de uma vez, sendo que é sempre correspondente à quantidade de nºs de telefone que ele possui.
Exemplo:
Crio um contato com nome "Teste A" e com os telefones 123, 456, 789 e 000. Este contato é salvo no banco de dados e é gerado um código 1500 para ele. Até aí, o banco de dados só possui 1 registro em Contact, 4 em Contact_phone e 4 em Contact_has_Contact_phone. Porém, quando é feita uma consulta por todos os registros (um SELECT * FROM Contact), é retornada uma lista possuindo o contato "Teste A" quatro vezes, cada um com todos os seus 4 números de telefone.
Qual poderia ser o problema?
Abaixo o código de tudo que é feito antes e durante a consulta:
MainJFrame.java/**
* Atualiza a tabela de contatos. Método executado sempre que a janela é aberta ou o botão ATUALIZAR é clicado.
*/
private void updateTable()
{
// adiciona todos os contatos da base de dados ao modelo da tabela
((ContactTableModel) this.contactsTable.getModel())
.setContacts(this.contactRepository.findAll());
}
// já dei um System.out.println na lista retornada por este método e o erro realmente vem daqui
public List<T> findAll() throws RepositoryException
{
try
{
getSession().beginTransaction();
List<T> result = this.session.createCriteria(getStoreClass()).list();
getSession().getTransaction().commit();
return result;
}
catch (Exception exception)
{
getSession().getTransaction().rollback();
throw new RepositoryException(exception);
}
finally
{
getSession().close();
}
}
O mapeamento da relação entre as duas entidades:
Contact.javapublic class Contact implements Cloneable, Serializable
{
...
/** Todos os números de telefone do contato. */
@ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@JoinTable(name="Contact_has_Contact_phone", schema="public",
joinColumns={@JoinColumn(name="Contact_Cd_Contact")},
inverseJoinColumns={@JoinColumn(name="Contact_phone_Cd_Contact_phone")})
private List<ContactPhone> contactPhones;
}
public class ContactPhone implements Cloneable, Serializable
{
...
/** Os contatos que possuem este número de telefone. */
@ManyToMany(fetch=FetchType.LAZY,
cascade={CascadeType.MERGE, CascadeType.PERSIST},
mappedBy="contactPhones")
private Collection<Contact> contacts;
}
SQL gerado durante a consulta:
Hibernate:
/* criteria query */ select
this_.Cd_contact as Cd1_0_1_,
this_.Ds_address as Ds2_0_1_,
this_.Dt_birthday as Dt3_0_1_,
this_.Ds_email as Ds4_0_1_,
this_.Nm_first_name as Nm5_0_1_,
this_.Nm_surname as Nm6_0_1_,
contactpho2_.Contact_Cd_Contact as Contact1_3_,
contactpho3_.Cd_contact_phone as Contact2_3_,
contactpho3_.Cd_contact_phone as Cd1_1_0_,
contactpho3_.Ds_phone as Ds2_1_0_,
contactpho3_.Nr_phone as Nr3_1_0_
from
public.Contact this_
left outer join
public.Contact_has_Contact_phone contactpho2_
on this_.Cd_contact=contactpho2_.Contact_Cd_Contact
left outer join
public.Contact_Phone contactpho3_
on contactpho2_.Contact_phone_Cd_Contact_phone=contactpho3_.Cd_contact_phone