Hibernate/JPA - EntityManger por Session  XML
Índice dos Fóruns » Java Enterprise Edition (Java EE)
Autor Mensagem
israel.fonseca
JavaBaby
[Avatar]

Membro desde: 13/10/2007 15:11:19
Mensagens: 88
Localização: Tubarão - SC
Offline

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?

Hibernate Reference wrote:
Never use the anti-patterns entitymanager-per-user-session or entitymanager-per-application (of course, there are rare exceptions to this rule, e.g. entitymanager-per-application might be acceptable in a desktop application, with manual flushing of the persistence context). Note that some of the following issues might also appear with the recommended patterns, make sure you understand the implications before making a design decision:

* An entity manager is not thread-safe. Things which are supposed to work concurrently, like HTTP requests, session beans, or Swing workers, will cause race conditions if an EntityManager instance would be shared. If you keep your Hibernate EntityManager in your HttpSession (discussed later), you should consider synchronizing access to your Http session. Otherwise, a user that clicks reload fast enough may use the same EntityManager in two concurrently running threads. You will very likely have provisions for this case already in place, for other non-threadsafe but session-scoped objects.
* An exception thrown by the Entity Manager means you have to rollback your database transaction and close the EntityManager immediately (discussed later in more detail). If your EntityManager is bound to the application, you have to stop the application. Rolling back the database transaction doesn't put your business objects back into the state they were at the start of the transaction. This means the database state and the business objects do get out of sync. Usually this is not a problem, because exceptions are not recoverable and you have to start over your unit of work after rollback anyway.
* The persistence context caches every object that is in managed state (watched and checked for dirty state by Hibernate). This means it grows endlessly until you get an OutOfMemoryException, if you keep it open for a long time or simply load too much data. One solution for this is some kind batch processing with regular flushing of the persistence context, but you should consider using a database stored procedure if you need mass data operations. Some solutions for this problem are shown in Chapter 6, Batch processing. Keeping a persistence context open for the duration of a user session also means a high probability of stale data, which you have to know about and control appropriately.


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?

Hibernate Reference wrote:
Detached Entities - If you decide to use the already discussed entity-per-request pattern, all loaded instances will be in detached state during user think time. The entity manager allows you to merge the detached (modified) state and persist the modifications, the pattern is called entitymanager-per-request-with-detached-entities. Automatic versioning is used to isolate concurrent modifications.


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

Israel


http://israelfonseca.blogspot.com/
[MSN]
Leonardo3001
GUJ Ranger

Membro desde: 04/07/2007 18:28:58
Mensagens: 975
Offline

É 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 .

Leonardo Veríssimo
-------------------------------------------------
Objectzilla
[WWW]
 
Índice dos Fóruns » Java Enterprise Edition (Java EE)
Ir para:   
Powered by JForum 2.1.8 © JForum Team