BugBuster 1.0 – Hibernate Exception: Illegally attempted to associate a proxy with two open Sessions
Abril 19, 2008
O referido erro também ocorre com mesagem semelhante:
Illegal attempt to associate a collection with two open sessions
Causa:
O erro é provocado quando um hiberObject associado a uma sessão tenta ser alterado por outra sessão do hibernate.
Solução:
Esqueça os métodos session.get/load/update você pode conseguir o mesmo efeito com session.refresh/merge.
Contexto do Problema:
Isso acontece devido a associação de um objeto gerenciado pelo hibernate (hiberOjbect) com a sessão que o carrega. Tecnicamente se um objeto foi carregado por uma sessão, até que o objeto seja desconectado (passando para o estado Detached) ele permanece associado a ela. O que pode ser feito invocando os métodos:
//Apenas se os relacionamentos do hiberOject //que possuem cascade="evict" eles serão também desconectados session.evict(hiberObject); session.clear(); session.close();
Se outra sessão tentar alterá-lo sem ele estar destacado da última sessão, o erro será lançado.
Problemas Típicos:
1. 0 Quando se deseja usar um objeto em outra sessão sem fechar a primeira use o evict, lembrando que se os relacionamentos não possuirem cascade=”evict” o efeito do método não servirá para eles e provavelmente o mesmo erro ocorrerá para o “proxy” dos relcionamentos (que podem ser coleções causando Illegal attempt to associate a collection with two open sessions) .
2.0 Em Aplicações WEB Java tipicamente carregamos um hiberObject e o setamos em alguma variável do contexto web (request, session, sevletContext), após algum uso pela camada de apresentação fazemos outra chamada a camada do hibernate usando esse mesmo hiberObject onde ocorre falha com o dito erro. Neste caso temos dois pontos:
- Se a sessão que o carregou anterior ainda estava aberta você recai no erro 1.0
- Caso a velha sessão já tenha morrido, o seu hiberObject não está mais conectado a mesma, porém os seus relacionamentos ainda podem ter algum “proxy” para a velha sessão. Nesse caso é mais simples usar um dos metódos:
//Caso queira reconectar e recarregar //no seu objeto os dados do banco session.refresh(detachedHiberObject); //Caso queira reconectar o objeto fazer um update no banco //de dados com as novas informações setadas no objeto connectedHiberObject = session.merge(detachedHiberObject);
O merge/refresh tem funções diferentes, mas ambos reconectam o objeto a uma sessão, seja a mesma ou não, sem provocar erro.
Parabéns Fabricio pelo Blog. Gostei da preocupação com desempenho… vou ter que colocar no meus favoritos.
Abraços e Boa sorte.
Obg Luciano! Aceito sugestões também =)
Abraço e tudo de bom.
Opa! Parabens! Gostei do objetivo do blog hehe! Uma sugestão apenas, acho que precisa melhorar apenas na formatação dos textos… hehe so isso! quando puder dar uma passada http://camilolopes.wordpress.com é sobre Java!!
flw!
Muito bom mesmo! Precisamos cada vez de blogs que explorem problemas comuns e até bizarros no desenvolvimento de software.
Parabéns!