Solução para Lazy Initialization com EJB3 + JPA(Hibernate) + JSF

Pessoal,

 Considerando que eu quero/preciso deixar todos os meus entitys beans mapeados com LAZY=TRUE (padrão), qual a solução mais amplamente utilizada e aceita para eu não pegar as famigeradas LazyInitializationException quando for acessar propriedades não inicializadas na minha página JSF? Considerem que, no caso dessa aplicação, as páginas JSF/managed beans acessam meus controllers/model facades que, por sua vez, estarão implementados como session beans EJB (Stateless ou Stateful, ainda não tenho certeza de qual dos dois utilizar).
 Se estas informações não estiverem claras ou detalhadas o bastante para que alguém possa ajudar, eu me coloco a disposição para explicar melhor o contexto do meu problema e o que pretendo fazer.

Desde já eu agradeço.

Não tenho nenhum projeto desenvolvido com hibernate, mas do pouco que conheco da tecnologia creio que um Servlet Filter seja a solução.
Dos testes que fiz não tive mais problemas com Lazy fectch.

Mais detalhes de como implementar em http://www.hibernate.org/43.html

[]s

Costumo usar Hibernate.initialize(Object obj); quando preciso que entidades com mapeamentos lazy=true disponibilizem todas suas propriedades e relacionamentos acessiveis.

Caso tenha acabado de ler o objeto, você não precisará usar o initialize, desde que voce acesse as propriedades dentro da mesma transaction.

Pelo JPA há 2 maneiras que conheco para resolver esse problema:

  1. No seu método que faz a pesquisa voce usa collection.size() para inicializar a colecao e automaticamente essa collection eh alimentada.

public MeuObjeto findByPrimaryKey(Integer key){ MeuObjeto obj = em.find(MeuObjeto.class, key); obj.colecao().size(); return obj; }

  1. voce pode criar uma namedQuery e utilizar join fetch, que ele popula a colecao para voce:
from Objeto meuObjeto join fetch meuObjeto.colecao

Marco.

Pessoal,

A todos que responderam, eu agradeço bastante. Vou estudar e testar cada alternativa e depois relato aqui os resultados e a decisão que tomei.

[]'s

Dentre as opções postadas, a mais ‘elegante’ é usar um Filter para garantir que a sessão seja única do iníco ao fim do request (como o aeugenio sugeriu). Ela garante que cada chamada lazy se comporte como você deseja: traz os dados apenas quando necessário. Você evitará de ficar fazendo códigos para inicializar o objeto ou setar o tamanho em cada requisição ao db.

O problema em usar um Hibernate.initialize(Object obj); é que este código deverá ser implementado em seu DAO ou até no get do seu objeto list. Ambos os casos não são bons por misturar as coisas. Ao usar o size o problema é o mesmo.

Ressalto que todos funcionam, mas recomendo que você utilize o Filter.

Na minha opiniao a melhor solucao eh fazer a busca atraves de JOIN FETCH:

  1. simples, basta criar uma namedQuery;
  2. faz parte da especificacao JPA;
  3. nao fica preso a implementação do hibernate.

Marco.

Pessoal,

A minha dúvida é, com o modelo de programação EJB3 que estou utilizando, ou seja, JSF para visão, controladores implementados como EJBs, que por sua vez acessam DAOs, que são EJBs Stateless e que fazem referência a um EntityManager injetado pelo container (vide arquiteura do sistema de exemplo do site do Hibernate -- [url=http://www.hibernate.org/400.html]CaveatEmptor JPA/EJB 3.0[/url]), não haveria uma solução que tirasse proveito dessa arquitetura? Em outras palavras, a Sun, com o advento do EJB3, não forneceu nenhuma solução padrão para esse tipo de problema tão comum em aplicações web (LazyInitializationException)? Ah sim, antes que alguém mencione, não é uma opção minha utilizar o Seam.