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.