Hibernate/JPA - EntityManger por Session

Fora o possível problema de estouro de memória, existe alguma outra desvantagem em se usar um EntityManger com escopo de Session numa aplicação JSF?

A referencia do hibernate indica 3 problemas, o primeiro eu não intendi ao certo mas acho que não é meu caso. O segundo é sobre ter que fazer um novo entityManger quando algum erro for disparado, mas isso não é custoso nem problemático. O terceiro problema realmente faz sentido.

E só por curiosidade, é custoso usar muitos .merge(), é recomendado ou não o utilizar? Porque na real, essa de fazer o entitymanger por session é para evitar o uso dos merges, pensava eu que talvez isso fosse dar mais desempenho no sistema. A referencia do hibernate até reconhece esse parttern, então ele realmente é “legal” de se usar?

Desde já agradeço as palavras de sabedoria. Obrigado. :slight_smile:

Israel

É preciso entender uma coisa: existem dois tipos de conexão: representados pelo objeto Session (que você enxerga) e pelo objeto Connection (que a Session encapsula).

Entenda que uso de sessão (HttpSession) é custoso. Implica em deixar alguns segundos um recurso bloqueado (enquanto o usuário está olhando a sua página) para apenas alguns milisegundos de processamento real. Tipo: uns 95% do tempo, o recurso está bloqueado sem fazer nada. Isso não é problema se você tem muita memória e o está manipulando simples objetos POJO.

A coisa complica quando se trata de objetos Connection, pois o banco de dados não vai disponibilizar uma quantidade infinita deles, e você tem que economizar o máximo possível. Os caras do Hibernate sabem disso, e recomendam que, depois de encerrada a requisição, a Session seja fechada para que esta feche a Connection, liberando recursos de banco. O uso do merge tem um custo, claro! Mas é pouco considerado o custo de manter a posse de uma Connection por muito tempo.

Existem tecnologias como o Seam, ou o próprio EJB com os seus statefull session beans, que permitem que o EntityManager dure por uma sessão, não uma requisição. Mas aí existe uma mágica: ao termino da requisição, a Session fecha sua Connection (unbind) com o framework mantendo a Session viva na sessão. Em uma nova requisição, o framework pega a mesma sessão e abre uma nova Connection (bind). Por não contar mais com a propriedade ACID vinda do banco, o Hibernate usa um lock otimista próprio para garantir a unicidade da transação.

Dá pra fazer esse esquema à mão e está explicado em http://www.hibernate.org/43.html#A5 .