Olá,
Meu problema: a classe que controla meu webform chama o webservice para materializar um objeto que possui collections e mapeamentos 1-1, quando o webservice retorna o objeto para minha classe de controle do webform e eu tento acessar uma collection no objeto recebo a infame org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: SisUsuario.unidades, no session or session was closed
Não quero desabilitar o lazy loading para evitar perda de performance em outras partes do aplicativo que usam a mesma classe que é buscada no banco. Devido como a API de acesso ao banco foi feita, fica dificil achar uma solução que se encaixa na idéia da API. O método em questão é:
[code]public boolean find(EntityObject entityObj){
boolean achou = false;
Session session = openSession(entityObj);
Transaction transaction = startTrans(session);
try {
EntityId id = new EntityId(entityObj);
session.load(entityObj,id.getKey());
commit(transaction);
achou = true;
} catch (Exception ex) {
//System.out.println(ex.getMessage());
ex.printStackTrace();
rollback(transaction);
}
return achou;
}[/code]
Passo o objeto com as PKs preenchidas para ser recuperado na base. Tentei session.evict(), mas o problema persiste. Alguem tem alguma ideia de como desabilitar o lazy loading neste caso? Algum método que posso chamar antes do session.load()?
Agradeço previamente qualquer ajuda,
Sérgio
Veja bem…a sua sessão esta aberta durante o LOAD eu presumo…pois senão seria impossível realizar a consulta. Mas ae o problema é que em algum lugar o qual você não dissse a sessão é fechada.
Os objetos de cache da JPA, acredito eu, ficam no chace de 2º nível. Ou seja estão disponíveis para qualquer sessão aberta. Se vc abrir uma sessão na hora em que for exibir estes dados não terá problemas. Talvez esta não seja a solução só estou tendando te dar uma direção.
Vou tentar esclarecer as duvidas, pois não foi eu quem encapsulou o hibernate nesta API. Só estou tentando arrumar um problema da maneira correta (seguindo a idéia da API), na verdade o problema inicial era com sessões abertas e nunca fechadas e com NonUniqueObjectException sendo jogado quando eu tentava carregar o mesmo objeto 2 vezes (em lugares diferentes) usando uma sessão estática.
Resolvi o problema do NonUniqueObjectException usando o SessionFactory.getCurrentSession(), que segundo minha pesquisa mantém uma sessão por thread.
Voltao meu problem atual…Sim, a sessão esta aberto durante o load. Não é chamado um session.close() em momento nenhum, mas eu li em algum lugar que o transaction.commit() faz isso parece ou eu deveria chamar o session.close explicitamente? A sessão usada para fazer comunicação com o banco é recuperada por SessionFactory.getCurrentSession(). A configuração de cache de 2º nivel esta desativada (não sei porque).
Meu problema é transportar um objeto pelo webservice com tudo que o bean do webform precisa em uma única chamada, em vez de varias chamadas pingadas para carregar mapeamentos 1-1, 1-n e n-n para diminuir o overhead e ainda sim manter o lazy loading para as classes “locais” (em relação ao webservice) que executam regras de negócios em cima de outras classes mapeadas no banco de dados. Tudo isso sem alterar o código existente atualmente que usa esta API.
Surgiu outra duvida, quando vou materializar um objeto, basicamente o que acontece agora é:
- session = sessionFactory.getCurrentSession()
- transaction = session.beginTransaction()
- load/saveOrUpdate/list/get/…
- transaction.commit()
(no meio disso tem try/catch dando rollback e coisas assim quando necessario)
Fui testar uma alteração aqui agora e vi que a sessão esta sendo fechada quando dou o commit(). Isso quebra minhas pernas na hora que vai acontecer o lazy loading de uma collection no caso para uma classe qualquer que cuida de uma regra de negocio…
Ta certo esse commit ali? Tem como fazer um load (ou qualquer outra operacao) sem usar transaction? (ele joga uma HibernateException quando nao uso transação)