localcontainerentitymanagerfactorybean entitymanagerfactory data baeldung java spring jpa entitymanager

java - data - Inyectar EntityManager vs. EntityManagerFactory



spring jpa configuration (4)

Creo que esto ya ha sido bien cubierto, pero solo para reforzar algunos puntos.

  • El DAO, si es inyectado por Spring, es un singleton por defecto . Tienes que establecer explícitamente el alcance a prototipo para crear una nueva instancia cada vez.

  • El administrador de entidades inyectado por @PersistenceContext es seguro para subprocesos .

Dicho esto, tuve algunos problemas con un DAO singleton en mi aplicación multihilo. Terminé convirtiendo el DAO en un bean instanciado y eso resolvió el problema. Entonces, aunque la documentación puede decir una cosa, es probable que desee probar su aplicación a fondo.

Seguir:

Creo que parte de mi problema es que estoy usando

@PersistenceContext(unitName = "unit", type = PersistenceContextType.EXTENDED)

Si usa PersistenceContextType.EXTENDED, tenga en cuenta que debe, si lo entiendo correctamente, cerrar manualmente la transacción. Mira this hilo para más información.

Otro seguimiento:

Usar una DAO instanciada es una muy mala idea. Cada instancia del DAO tendrá su propio caché de persistencia y los cambios a un caché no serán reconocidos por otros beans DAO. Perdón por el mal consejo.

Una larga pregunta, por favor tengan paciencia conmigo.

Estamos usando Spring + JPA para una aplicación web. Mi equipo está debatiendo sobre inyectar EntityManagerFactory en GenericDAO (un DAO basado en Generics algo en las líneas proporcionadas por APPFUSE, no usamos JpaDaosupport por algún motivo) sobre la inyección de un EntityManager . Estamos usando "persistencia administrada por la aplicación".

Los argumentos en contra de inyectar un EntityManagerFactory es que es demasiado pesado y, por lo tanto, no es obligatorio, el EntityManager hace lo que necesitamos. Además, como Spring crearía una nueva instancia de un DAO para cada solicitud web (lo dudo) no habrá problemas de concurrencia ya que en la misma instancia de EntityManager se comparten dos subprocesos.

El argumento para inyectar EFM es que es una buena práctica sobre todo, siempre es bueno tener un control para una fábrica.

No estoy seguro de cuál es el mejor enfoque, ¿alguien puede por favor iluminarme?


Descubrí que establecer la anotación @Repository Spring en nuestros DAO y tener EntityManager administrado por Spring e inyectado mediante la anotación @PersistenceContext es la forma más conveniente de hacer que todo funcione con fluidez. Se beneficia de la seguridad de subprocesos del EntityManager compartido y la traducción de excepciones. De forma predeterminada, el EntityManager compartido administrará las transacciones si combina varios DAO de un administrador, por ejemplo. Al final, descubrirá que sus DAO se volverán anémicos.


Estoy resumiendo lo que finalmente he reunido. De la sección " Implementación de DAO basada en JPA simple " en la referencia de primavera:

Aunque las instancias de EntityManagerFactory son seguras para hilos, las instancias de EntityManager no lo son. El JPA EntityManager inyectado se comporta como un EntityManager obtenido del entorno JNDI de un servidor de aplicaciones, tal como lo define la especificación JPA. Delega todas las llamadas al EntityManager transaccional actual, si existe; de lo contrario, recurre a un EntityManager creado recientemente por operación, lo que hace que su uso sea seguro para subprocesos.

Esto significa que según las especificaciones de JPA, las instancias de EntityManager no son seguras para hilos, pero si Spring las maneja, se vuelven seguras para hilos.

Si está utilizando Spring, es mejor inyectar EntityManagers en lugar de EntityManagerFactory.


Los pros y contras de inyectar EntityManagerFactory vs EntityManager están detallados en los documentos de Spring here , no estoy seguro si puedo mejorar eso.

Al decir eso, hay algunos puntos en su pregunta que deberían aclararse.

... Spring crearía una nueva instancia de un DAO para cada solicitud web ...

Esto no es correcto. Si su DAO es un bean de Spring, entonces es un singleton, a menos que lo configure de otra manera a través del atributo scope en la definición de bean. Instanciar un DAO para cada solicitud sería una locura.

El argumento para inyectar EMF es que es una buena práctica sobre todo, siempre es bueno tener un control para una fábrica.

Este argumento realmente no se sostiene. La buena práctica general dice que un objeto debe ser inyectado con los colaboradores mínimos que necesita para hacer su trabajo.