EntiyManager, qual o modo correto de se utilizar em uma aplicação Java EE?

Boa noite pessoal, uma dúvida que sempre tive com relação ao EntityManager foi sobre seu escopo em um ambiente J2EE não gerenciado.
Abrir e fechar a cada transação? Abrir e fechar a cada operação de negócio? Abrir e fechar a cada Requisição HTTP?

Andei lendro sobre isso mas não encontrei uma resposta clara (ou não consegui entender :frowning: ).

Suponha que tenho uma aplicação com struts 2 e hibernate, e quando vou persistir o objeto X a seguinte sequência de acontende:

action -> bo -> dao

Bem, se eu fechar a cada transação, se o objeto X possuir uma lista LAZY e eu fizer X.getLista() na minha action vou obter um org.hibernate.LazyInitializationException.
Além disso este modo me traria outro problema:

Se uma operação de negócios envolver várias entidades e ocorrer um erro na persistência de alguma, um rollback não teria o resultado esperado, pois o escopo não envonve a operação toda, ele é para cada entidade.

Neste caso uma solução seria criar o entiry manager na camada BO e injetálo no DAO?
Ou ainda utilizar somente um EntityManager para a requisição http?

Atualmente estou abrindo um EntityManager para cada dao mas não estou fechando eles, isso é aceitável?

Agradeço a contribuição.
Abraços

Para evitar problemas de Lazy em páginas você pode usar patterns como o Open Session in View: http://community.jboss.org/wiki/OpenSessioninView

Existem muitos frameworks para lhe ajudar com JPA/Hibernate, como o Seam por exemplo. Ele faz gerenciamento de transação, injeta EntityManager controlando todo seu ciclo de vida, sem vc precisar se preocupar em finalizar o EntityManager e tbm prevê a aplicação contra erros do tipo LIE nas páginas, sem vc ter que implementar o pattern que sugeri acima. Leia um pouco aqui: http://docs.jboss.org/seam/2.1.2/reference/en-US/html/persistence.html

Se vc não usa framework algum com o EntityManager, cuidado, vc NÃO deve manter seus EntityManagers abertos. Se vc fazer isso, em pouco tempo vc vai ter sérios problemas com pool de conexões, uma vez que vc obtem uma sessão com o banco e não devolve para o pool. A recomendação é que vc trabalhe com um entitymanager ativo por “Unit of Work”, ou seja, a atomicidade de uma operação do usuário com o sistema… geralmente em aplicações web isso se dá em um ciclo de request e response. Se sua transaçao é maior do que isso, vc pode armazenar o contexto de seu entitymanager provisóriamente na sessão web, e depois fecha-lo no final da transação. Frameworks como o Seam e o SpringWebFlow fazem parecido quando precisam lidar com Transações Extendidas e podem ajudar tbm nestes casos.

Um livro que sempre indico, qual aborda este e outros temas relevantes sobre JPA e Hibernate é o JavaPersistence With Hibernate (ele tbm possui uma versão traduzida). Ele explica em detalhes a abordagem JavaSE e Java EE para se trabalhar com JPA.