2011-12-23 17 views
6

He creado algunas cosas de JPA en el pasado que usaban una instancia de javax.persistence.EntityManager por instancia de DAO; esta es la forma en que se configuran la mayoría de los ejemplos.JPA EntityManager ¿Estático o Instancia?

public class BaseDaoThatEveryDaoExtends { 
    @PersistenceContext 
    private EntityManager entityManager; 
} 

he tropecé con el código que utiliza un estáticajavax.peristence.EntityManger inyectado por una anotación de PersistenceContext, el arquitecto me dice que esto no causa ningún problema y nunca tuvo ningún problema incluso en una aplicación en clúster con JTA y un XA fuente de datos:

public class BaseDaoThatEveryDaoExtends { 
    @PersistenceContext 
    private static EntityManager entityManager; 
} 

Por lo que yo puedo decir que esto es un anti-patrón que el EntityManager mantiene cierta información de estado y lo que es estática hace que la aplicación del estado entero de ancho. Además, esto hace que las clases sean muy difíciles de probar.

¿Hay otros inconvenientes para hacer esto o es esta una forma estándar de usar un EntityManager?

Respuesta

1

EntityManager mantiene sus datos usando un hilo local, por lo que puede estar bien tener una referencia estática ya que todos los hilos que acceden a él se manejarán de forma independiente. De hecho, no me sorprendería si el contexto EJB se mantiene en el EntityManager de una manera estática, usando un patrón singleton.

Personalmente, nunca lo definiría de forma estática. Parece innecesario, y en el peor puede tener algunos efectos secundarios imprevistos.

Un problema que puedo ver es la capacidad de acceder de forma inadvertida la entityManager de un método estático:

public class BaseDaoThatEveryDaoExtends { 
    @PersistenceContext 
    private static EntityManager entityManager; 

    public static void doSomeStaticWork(){ 
     ... 
     entityManager.doSomething; //NPE possible! 
    } 
} 

pude ver el EntityManager no se inyecta y que resulta en un NPE en este caso.

Aparte de eso, puede haber algunos problemas con las pruebas/burlas con el EntityManager.

+0

Una NPE también es posible cuando se construye manualmente una instancia de DAO en lugar de inyectarla e invoca los métodos de instancia en ella. Para que no sea realmente un argumento. – BalusC

+0

Excepto que no tiene que construir el BaseDaoThatEveryDaoExtenses, simplemente llame a BaseDaoThatEveryDaoExtends.doSomeStaticwork() que puede dar como resultado un NPE. –

0

EntityManagerFactory garantiza la seguridad de subprocesos, por lo que creo que esta es la forma "correcta": Utilice la EMF en las ubicaciones de subprocesos no seguros y proteja al EntityManger de los problemas de subprocesamiento.

4

Creo que el principal riesgo no está en EntityManager, sino en el contexto de la aplicación que se adjunta al administrador de entidades cuando se usa.

Supongamos que tiene dos clientes diferentes que hacen una solicitud a su servidor, ambos invocan dos métodos diferentes de su aplicación, ambos ejecutados en diferentes subprocesos, pero ambos usan el mismo administrador de entidades.

Por lo que sé, el administrador de la entidad tendrá un único contexto adjunto, este contexto será compartido por ambos clientes. Cada vez que cargue una instancia en el contexto, estará disponible para los hilos a través del administrador de entidades compartido. ¿Qué pasará si manipulan los datos de los demás? ¿Qué pasará si utilizan una configuración de aislamiento de transacción diferente ?. ¿Cómo puede estar seguro de que el cliente 1 no está alterando los datos que utiliza actualmente el cliente 2?

¿Qué pasa si uno de los clientes invalida el contexto? ¿Qué hará el otro? ¿Cómo manejas la concurrencia de esta manera?

Cuestiones relacionadas