Fórum Dúvida Collections para Mapeamento em JPA #395199

08/02/2011

0

Salve galera! Gostaria de saber de vcs qual a melhor opção de mapeamento em JPA Collection, List ou Set Realizando testes com JPA+Hibernate 3.5.0 Final descobri o seguinte:
Considerando as seguintes Entitys Class:
Pessoa (Pessoa possui uma lista de Email e Endereços)
Email
Endereco
Usando Set<> 1° Se eu uso Set<> com
 fetch=FetchType.EAGER
nos mapeamentos funciona! Os seja, o metodo find do EntityManager traz os Sets preenchidos!
2° Se eu uso Set<> com
fetch=FetchType.LAZY
nos mapeamentos o método find do EntityManager retorna o seguinte erro:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:

3. Quando utilizo Set mesmo sem fazer
fetch=FetchType.EAGER
consigo fazer o seguinte jp ql:
select p from Pessoa p 
join fetch p.emailSet em
join fetch p.enderecoSet en
where p.pesId = 1

4. Outro problema que encontrei utilizando Set<> é o seguinte:
Set não aceita dados duplicados na lista como por exemplo uma lista de nomes: Paulo
Paulo
Felipe Se adiciono estes nomes em um Set os dados duplicados serão descartados ficando assim: Paulo
Felipe =====================================================================================
Usando List<> 1° Se eu uso List<> com
fetch=FetchType.EAGER
nos mapeamentos o método find do EntityManager retorna o seguinte erro:
org.hibernate.HibernateException: cannot simultaneously fetch multiple bags

2° Se eu uso List<> com
fetch=FetchType.LAZY
nos mapeamentos o método find do EntityManager retorna o seguinte erro:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:

3. Quando utilizo List de nenhuma maneira consigo fazer o seguinte jp ql:
select p from Pessoa p 
join fetch p.emailList em
join fetch p.enderecoList en
where p.pesId = 1

pois tenho o seguinte erro:
org.hibernate.HibernateException: cannot simultaneously fetch multiple bags

4. Utilizando List eu consigo fazer o seguinte jp ql e funciona!
select p from Pessoa p join fetch p.emailList
Só não consigo entender porque funciona com Set e não Funciona com List alguem puder me explicar? Devo utilizar Collection, List ou Set? Onde estou me perdendo?
Rogério Martins

Rogério Martins

Responder

Posts

08/02/2011

Davi Costa

O problema do Lazy, é arquitetural,
é muito comum acontecer, talvez vc deva usar o Spring e sua entidade não tem nenhuma sessão aberta para vc simplesmente dar um get e ele abrir uma conexão do banco para fazer essa pesquisa sobe demanda.

Para sua lista de Set se for um objeto complexo (diferente de uma lista de String), vc deve sobrescrever o equals e o hashCode para um atributo q não se repete, como de repente vc pode usar o id. O nome pode se repetir.

Para os erros do List, eu teria que estar mais contextualizado, mas posso lhe adianta se nas classes envolvidas no mapeamente tiver muitos Eager, dá esse erro que vc citou. talvez sua classe só tenha um EAGER, mas se a classe que vc chamu tiver outros EAGER e ele e os EAGERs mais outros, assim o hibernate se perde.

Geralmente o que eu faço é deixar Eager quando realmente é útil e no serviço ao invez de recuperar via  objeto.getSuaDependencia() e fugir do lazyException é chamar via um serviço, por exemplo:
service.recuperaDependenciasObjeto(objeto)... e por aí vai.

Espero ter dado alguma luz

Att Davi
Responder

Gostei + 0

11/02/2011

Dyego Carmo

Sugiro sempre List,

Lembrando que o Hibernate tem uma serie de "dores de barriga" com coleções complexas...

Principalmente aquelas do tipo LAZY dentro de updates (em.merge())...

Problemas arquiteturais e que a super "JBoss" se recusa a aceitar como BUG.

Mas a resposta do davi esta bem consistente.

Responder

Gostei + 0

12/02/2011

Rogério Martins

Tudo bem, qual seria a solução para o jp ql abaixo:

select p from Pessoa p 

join fetch p.emailList em

join fetch p.enderecoList en

where p.pesId = 1
Responder

Gostei + 0

12/02/2011

Robson Teixeira

Olá Rogerio
 
   concordo com a resposta do Davi está excelente.
   com relação a sua ultima query postada o erro dela me parece que o seu provedor de persistencia não deixa fazer esses 2 join teste colocando virgula entre eles ou na anotação de 1 desses atributos eu colocaria fetch=FetchType.EAGER para trazer os e-mails ou endereços.

att
 robson
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar