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.