Entity Manager & Persistence Context

Tutorial de JPA persistence.xmlHasta el momento solo hemos trabajado con el Entity Manager para realizar las operaciones básicas, pero existen detalles más finos que es necesario entender para convertirnos en expertos de JPA. Cuando trabajamos con JPA es común interactuar con el Entity Manager, ¿pero que tanto sabemos acerca de los Persistence Context en realidad?

 

Primero que nada, tenemos que saber que el Persistence Context se crea mediante un Persistence Unit y el Entity Manager se crea a partir de un Persistence Context, veamos la siguiente imagen para entender mejor:

persistence context

 

Veamos que todo parte del archivo persistence.xml del cual ya hablamos anteriormente, en este archivo se definen los Persistence Unit, y mediante estos es creado el Persistence Context, el Persistence Context tiene la finalidad de delimitar el alcance de las transacciones, pero también está delimitado a administrar las Entidades definidas por el Persistence Unit con el que fue creado.  Adicionalmente, el Entity Manager hace referencia a un Persistence Context el cual será utilizado para administrar las entidades y las transacciones.

 

Una de las ventajas de tener varios Persistence Unit, es que nos permite definir diferentes configuraciones para cada uno, de esta manera podemos delimitar las entidades de cada módulo e incluso una configuración de base de datos diferentes para cada uno.

 

Container-Managed Entity Manager

 

Básicamente existen dos formas de trabajar con JPA, la más simple es cuando lo utilizamos en aplicaciones SE o de escritorio y la segunda forma que es la que estudiaremos en esta sección, es cuando lo utilizamos en ambientes de Java EE con EJB.

La principal característica de utilizar Entity Manager administrado por el contenedor, es que es el mismo Container el que se encarga de abrir y cerrar las transacciones, por lo que el programador solo se preocupa por implementar la lógica de negocio despreocupándose en la totalidad de las transacciones.

En ambientes Java EE se suele utilizar la anotación @PersistenceContext  para crear el EntityManager, como veremos en el siguiente EJB.

 

 

Cuando utilizamos la anotación @PersistenceContext  el contenedor inyecta de forma automática una referencia válida del EntityManager creado a partir de la Persistence Unit JPA_PU, de esta forma, el programador podrá utilizar el EntityManager en cualquier método que defina, y las transacciones será administradas de forma automática.

 

Ahora bien, existen dos variantes de los Container-Managed, Transaction-Scope y Extended, los cuales son utilizados en circunstancias diferentes. Para utilizar una variante o la otra, es necesario definirlo en la anotación @PersistenceContext  mediante la propiedad type. Los valores posibles son TRANSACTION  y EXTENDED  como veremos a continuación:

 

 

En caso de no definir la propiedad type, el valor por default será TRANSACTION, lo cual está bien, porque es por lejos la variante más utilizada.

 

Transaction-Scope

 

La variante Transaction-Scope es la variante utiliza por default, por lo que no es necesario definir la propiedad type para utilizarla. Esta variante tiene la particularidad de que el contexto de persistencia solo será válido durante le ejecución de la operación de negocio, una vez que la operación termine el contexto de persistencia se destruye y todas las entidades relacionadas con el Entity Manager será descartadas.

Este tipo de estrategias se utiliza para EJB sin estado como los @Stateless, pues cada invocación a una operación de negocio se espera que realice una acción, persista y retorne un resultado, y cada ejecución tendrá un contexto de persistencia diferente, garantizando de esta forma que el servicio siempre arroje el mismo resultado para la misma entrada.

Veamos un ejemplo de un servicio de creación de empleados:

 

 

Imaginemos el siguiente escenario, tenemos una aplicación que carga el empleado en pantalla utilizando el método getEmployeeById, esta consulta al empleado mediante el ID y lo retorna, la aplicación utiliza el empleado consultado para mostrarlo en pantalla, luego, modificamos el nombre del empleado y guardamos los cambios mediante el método updateEmployeeName.

Lo primero que hace la aplicación es consultar el empleado, hasta aquí todo bien, pero cuando actualizamos el nombre del empleado, vemos que realizamos un find mediante el ID del empleado, podríamos pensar que como ya lo hemos consultado anteriormente mediante el método getEmployeeById este solo lo retomará del cache sin realizar una nueva consulta a la base de datos, sin embargo, Transaction-Scope garantiza que cada ejecución crea un nuevo PersistenceContext en blanco, por lo que el empleado que anteriormente ya habíamos consultado será nuevamente consultado, debido que en la segunda llamada al método updateemployeeName el Persistence Context está en blanco.

 

No te preocupes por las anotaciones @TransactionAttribute, más adelante las explicaremos por ahora pasémoslas por alto.

 

Extended

 

La segunda variante es Extended, que como su nombre nos lo indica, se trata de un Contexto de Persistencia Extendido, donde el contexto persistirá durante todo el tiempo de vida de la sesión, sin importar el número de operaciones o transacciones que se realicen.

A diferencia de Transaction-Scope, en esta variante todos los cambios realizados en el Persistence Context seguirán vigentes, por lo que cada ejecución que realicemos se favorecerá de las ejecuciones pasadas.

Este tipo de variante es utilizada cuando trabajamos con EJB con sesión como el @Stateful, veamos el mismo ejemplo anterior pero esta vez utilizando un EJB con sesión y la variante Extended.

 

 

En este caso las cosas son un poco diferentes. Primero que nada, se realiza la consulta del empleado mediante el método getEmployeeById y el empleado es retornado, cuando la ejecución del método termina, el Persistence Context continúa existiendo, por lo que cuando se realiza la actualización del nombre del empleado y se realiza la consulta del empleado, el Entity Manager ya no consulta al empleado, pues este ya fue consultado en el método anterior. Finalmente, el nombre es actualizado y al terminar el método se hace un commit de la transacción. Al finalizar el método el Contexto de persistencia continua activo hasta que la sesión finaliza.

 

 

Application-Managed Entity Manager

 

La segunda forma de trabajar con JPA es delegar al programador la responsabilidad de administrar las transacciones, este escenario se da con mucha más frecuencia en aplicaciones de escritorio, aunque existen escenarios donde es utilizado en entornos de Java EE.

Básicamente el programador tiene que crear el EntityManager a través del EntityManagerFactory y tiene que abrir y cerrar las transacciones cada vez que requiera.

Veamos cómo quedaría el escenario anteriormente planteado utilizando application-managed:

Podemos apreciar que el constructor de la clase estamos creando manualmente el EntityManager en lugar de simplemente inyectarlo como el Container-Managed, la otra diferencia es en el método updateEmployeeName, ya que para poder persistir los cabios tenemos que abrir y cerrar la transacción con los métodos beign y commit.

 

AnteriorÍndiceSiguiente

Artículos relacionados

Declarar entidades con @Entity Una de las grandes ventajas de JPA es que nos permite manipular la base de datos a través de objetos, estos objetos son conocidos como Entity, las cua...
Mapeo de enumeraciones con @Enumerated Una de las ventajas de utilizar enumeraciones en Java, es podemos limitar los valores posibles para una propiedad, forzando a los desarrolladores a ut...
Trabajar con objetos pesados @Lob JPA nos permite mediante la anotación @Lob mapear con la base de datos objetos pesados, como podría ser imágenes, xml, binarios, cadenas de texto exte...

Oscar Blancarte

Ideológico, Innovador y emprendedor, Padre, Tecnólogo y Autor, amante de la ciencia y la tecnología en todos sus colores y sabores. Arquitecto de software & Full Stack Developer con experiencia en la industria del desarrollo de software y la consultoría. Amante de la programación y el Ajedrez.

4 comentarios en “Entity Manager & Persistence Context

  1. Buena tarde, tengo dos unidades de persistencias en mi proyecto y dos daos que crean un entitymanager apuntando cada cual a una unidad de persistencia, requiero hacer un join con tablas que se encuentran en cada una de las unidades de persistencias, pero al realizarla sobre un entitymanager me dice que la otra tabla o vista no existe.

    saludos!

    1. Si este error es normal por que seguramente solo tienes una entidad en cada PU, lo que tendrias que hacer en tal caso, es registrar las dos Entity en el PU donde necesites hacer el join. De lo contrario, el PU no podra resolver la segunda entidad

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *