2012-05-26 15 views
65

Tengo el siguiente método.¿Debería estar cerrado JPA Entity Manager?

public Profile readUser(String email){ 
    EntityManager em = EMF.get().createEntityManager(); 
    return em.find(Profile.class, email); 
} 

¿Está bien el uso anterior del administrador de entidades? O es necesario cerrar em? Cualquier sugerencia, por favor.

+0

posible duplicado de [¿Tengo que cerrar() cada EntityManager?] (Http://stackoverflow.com/questions/220374/do-i-have-to-close-every-entitymanager) – rds

+0

No, simplemente no . A menos que desee fugas ... – DN1

Respuesta

105

Supongo que la respuesta es: depende.

Su administrador de entidad es la clave para obtener acceso al contexto donde residen las entidades. Si su aplicación es una aplicación JSE, debe considerar cuál es la expectativa de vida de su contexto.

Consideremos que creará un administrador de entidades por solicitud del usuario. Por lo tanto, mientras asista a una solicitud determinada, mantendrá abierto el administrador de su entidad y cuando termine con ella, la cerrará.

En una aplicación JSE puede haber considerado que le gustaría mantener el administrador de entidades abierto durante toda la vida de la aplicación (suponiendo que no está tratando con grandes cantidades de datos) y luego cerrarla cuando se cierra la aplicación .

En pocas palabras, cuando lo abres y cuando cierras depende completamente de tu estrategia y tu diseño. Lo cierra cuando ya no necesita las entidades en su contexto.

En su ejemplo que no es evidente, pero ya que está creando el EM en el método, debe cerrarlo antes de volver, de lo contrario ya no tendrá acceso a él (a menos que lo mantenga en alguna registro, que no es evidente en el código).

Si no cierra, sus entidades se mantendrán adjuntas, incluso después de que haya terminado de usarlas. Su contexto se mantendrá vivo incluso cuando ya no pueda acceder a su EM.

El JPA Specification contiene más detalles. En la sección 7.7 Aplicación gestionados Persistencia Contextos que dice:

Cuando se utiliza un gestor de entidad de aplicación gestionados, la aplicación interactúa directamente con el gestor de la entidad del proveedor de persistencia fábrica para gestionar el gestor de ciclo de vida de la entidad y para obtener y destruir contextos de persistencia.

Todos los contextos de persistencia administrados por la aplicación se extienden en el alcance , y pueden abarcar varias transacciones.

El método EntityManagerFactory.createEntityManager y la EntityManagerclose y isOpen métodos se utilizan para gestionar el ciclo de vida de un gestor de entidad de aplicación gestionados y su contexto persistencia asociada. existe

El contexto de persistencia extendida desde el punto en el que el gestor entidad ha sido creado usando EntityManagerFactory.createEntityManager hasta que el gestor de la entidad es cerrado por medio de EntityManager.close.

Un contexto de persistencia ampliado obtenido del administrador de la entidad administrado por la aplicación es un contexto de persistencia independiente que no se propaga con la transacción .

[...] El método EntityManager.close cierra un administrador de entidades a libera su contexto de persistencia y otros recursos. Después de llamar al cerrar, la aplicación no debe invocar ningún otro método en la instancia EntityManager a excepción de getTransaction y isOpen, o se lanzará el IllegalStateException. Si el método de cierre es invocado cuando una transacción está activa, el contexto de persistencia permanece en administrado hasta que la transacción finaliza.

El método EntityManager.isOpen indica si el administrador de entidad está abierto. El método isOpen devuelve verdadero hasta que se haya cerrado el administrador de entidades . Para entender realmente cómo funciona esto, es vital comprender la relación entre el administrador de la entidad y el contexto.

Entonces, como puede ver, el administrador de entidades es la interfaz pública a través de la cual usted accede a sus entidades; sin embargo, sus entidades residen en un contexto, adjunto a su administrador de entidades. Comprender el ciclo de vida de los diferentes tipos de contextos responderá a su pregunta.

Los contextos de persistencia pueden ser de diferentes tipos. En las aplicaciones Java EE, puede tener contexto de persistencia con ámbito de transacción o contexto de persistencia ampliada. En la aplicación JSE, la naturaleza del contexto es controlada por el desarrollador.

Cuando solicita una entidad a su administrador de entidad, busca la entidad en su contexto adjunto, si encuentra la entidad allí, luego la devuelve; de ​​lo contrario, recupera la entidad de la base de datos. Las llamadas posteriores para esta entidad en contexto devolverán la misma entidad.

con ámbito de transacción

En una aplicación Java EE utilizando el contexto de persistencia con ámbito de transacción, la primera vez que acceder a su gestor de la entidad, comprueba si la transacción actual JTA tiene un contexto adjunto, si no hay contexto es aún presente, se crea un nuevo contexto y el administrador de la entidad está vinculado a este contexto. Luego, la entidad se lee desde la base de datos (o desde la memoria caché, si está presente) y se coloca en el contexto. Cuando la transacción finaliza (confirmación o reversión), el contexto deja de ser válido y las entidades que aparecen se separan. Este es el escenario clásico para beans de sesiones sin estado.

@PersistenceContext(unitName="EmplService") 
EntityManager em; 

Esto también significa que dependiendo de cómo diseñe sus transacciones, puede terminar con más de un contexto.

extendido-Persistencia Contexto

En una aplicación Java EE con beans de sesión con estado que te pueden gustar el contexto de sobrevivir a múltiples invocaciones de frijol, ya que no desea comprometerse hasta que el grano se ha marcado para la eliminación , ¿derecho? En esos casos, necesita usar un contexto de persistencia extendido. En este caso, el contexto de persistencia se crea cuando se necesita por primera vez, pero no se volverá inválido hasta que marque el bean statefull para su eliminación.

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

Esto significa que, independientemente de la instancia del gestor de la entidad que obtiene inyecta en este frijol en las llamadas posteriores de los métodos de beans de sesión con estado, puede estar seguro de que siempre tendrá acceso el mismo contexto, y por lo tanto, incluso las llamadas posteriores devolverán la misma instancia, porque es el mismo contexto.

Además, sus cambios no se eliminarán hasta que el bean esté marcado para su eliminación o los enjuague manualmente.

gestionados por la aplicación

Siempre se puede crear una instancia manualmente su fábrica de gestor de la entidad, y el gestor de la entidad. Esto es lo que normalmente harías en una aplicación JSE, ¿verdad?

Para este tipo de aplicaciones, normalmente no tiene un contenedor para manejar las transacciones de JTA, ¿verdad? Por lo tanto, utiliza las transacciones locales de recursos y usted es responsable de realizar o deshacer cambios manualmente.

Para este tipo de aplicación, cuando crea una instancia de su administrador de entidades, se le agrega automáticamente un contexto.

Dependiendo de su aplicación, puede decidir crear un administrador de entidades global cuyo ciclo de vida se adjunta a la vida de la aplicación. Es decir, un único administrador de entidades durante toda la vida de la aplicación. En estos casos, su contexto será creado y destruido con su administrador de entidades.

O bien, podría crear un administrador de entidades por conversación (es decir, transacción) con su usuario de la aplicación. El alcance en este caso lo determina usted, pero aún así, su contexto será creado y destruido con su administrador de entidades.

+0

Excelente respuesta, pero necesito saber: abrir y cerrar EntityManager varias veces durante una sesión ¿tiene un alto costo de rendimiento? Cree una instancia y ciérrela solo una vez, o cree una instancia/use/ciérrela en cada operación crud de base de datos, ¿cuál es el mejor enfoque? "depende" está bien, pero debe tener un uso más adecuado para la mayoría de los casos de uso. – tomurlh

+1

@tomurlh Por lo que a mí respecta, el costo de crear el 'EntityManager' debe ser insignificante. Desde mi punto de vista, EntityManager es solo una abstracción para tratar con la [unidad de trabajo] (https://martinfowler.com/eaaCatalog/unitOfWork.html) de la transacción actual. Creo que está perfectamente bien crear y destruir uno por transacción. Ahora, tiene otras implicaciones, porque los servidores 'EntityManager' como un caché transaccional para sus entidades y, por lo tanto, tener un alcance de transacción bien definido y tratar adecuadamente con entidades podrían aprovechar este caché. –

Cuestiones relacionadas