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

Operaciones b谩sicas

Operaciones b谩sicasUna parte esencial de utilizar JPA es saber utilizar las operaciones b谩sicas, operaciones mediante las cuales es posible consultar, persistir, actualizar y eliminar entidades, de estas operaciones estaremos hablando hoy.

 

Gran parte de la funcionalidad de JPA es expuesta por medio de la Interface EntityManager, de la cual ya hemos hablado con anterioridad, y es por medio de esta interface, que es posible realizar las operaciones b谩sicas. Las operaciones o m茅todos que exponen EntityManager son persist, merge, remove, find entre otras, que son sin duda las operaciones que m谩s utilizaremos los proyectos.

En la secci贸n anterior de este tutorial, hablamos de los estados de las entidades, las cuales ser谩 clave para entender c贸mo y cu谩ndo deberemos utilizar dichas operaciones.

 

Sin m谩s, las operaciones se describen a continuaci贸n:

as

Ciclo de vida de las Entidades

Tutorial de JPA persistence.xml

Entender el ciclo de vida de las Entidades es sin duda uno de los puntos cruciales de JPA, pues entender c贸mo es que una Entidad es gestionada por EntityManager nos permitir谩 entender mejor como es que JPA funciona y prevenir muchos errores en tiempo de ejecuci贸n.

Lo primero que debemos de entender, es que todas entidades que utilicemos con JPA, ser谩n administradas por el EntityManager, es por este motivo que hemos agregado este esta secci贸n al cap铆tulo de EntityManager.

 

Persistence Context:

Antes de entrar a los estados de las Entidades es importante entender un nuevo concepto que no hemos analizados en esta gu铆a, se trata del Contexto de persistencia (Persistence Context), este lo podemos ver como contenedor en donde se encuentra todas las Entidades administradas por el EntityManager. Cuando un nuevo EntityManager es creado a trav茅s del EntityManagerFactory este le asigna un Unidad de persistencia. as

Trabajar con objetos pesados @Lob

Tutorial de JPA @LobJPA 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 extensas, json, etc. Cualquier objeto que pueda tener un tama帽a muy grande o de longitud indefinida.

 

@Lob

 

La anotaci贸n @Lob es lo 煤nico que se requiere para indicarle a JPA que ese campo es un objeto pesado y que debe de tratarse como tal. Por lo general se utiliza con los arreglos de bytes, ya que permite almacenar cualquier cosa.

La anotaci贸n @Lob no tiene ning煤n atributo, por lo que solo ser谩 necesario definirla para que funcione. Otro punto importante es que esta anotaci贸n crear谩 una columna de tipo longblob en mysql y podr铆a variar seg煤n el manejador de base de datos utilizados, pero al final siempre ser谩 un campo para objetos pesados.

Para poner en pr谩ctica esta anotaci贸n, retomaremos la entidad Employee, en esta ya hab铆amos agregado la propiedad photo聽 de tipo byte[], en la cual vamos a almacenar la foto del empleado, sin embargo, no hab铆amos entrado en detalles. La entidad Employee se ve de la siguiente manera:

as

Estrategias de carga con @Basic

Tutorial de JPA @Basic@Basic es una anotaci贸n que nos permite controlar el momento en que una propiedad es cargada desde la base de datos, evitando que traer valores que no son necesario al momento de cargar el objeto. Esta anotaci贸n es utilizada generalmente para anotar objetos pesados, como una imagen o un archivo binario.

 

@Basic

 

En JPA existe dos conceptos que son claves para entender c贸mo es que JPA carga los objetos desde la base de datos y estos son claves para mejorar el rendimiento de la aplicaci贸n, estos conceptos se explican a continuaci贸n:

  • Lazy loading (Carga demorada): Los objetos de carga demorada no ser谩n cargados desde la base de datos cuando el objeto sea creado, pero ser谩 cargado en cuanto se acceda a la propiedad. De esta manera JPA identifica cuando la propiedad es accedida por primera vez para cargar el valor desde la base de datos.
    • @Basic( fetch = FetchType.LAZY )
  • Eager loading (Carga ansiosa o temprana): Este es la utilizada por default para la mayoria de las propiedades en JPA, a excepci贸n de las colecciones las cuales las analizaremos mas adelante.
    • @Basic( fetch = FetchType.EAGER )

as

Mapeo de fechas con @Temporal

Tutorial de JPA @Temporal

Mediante la anotaci贸n @Temporal es posible mapear las fechas con la base de datos de una forma simple. Una de las principales complicaciones cuando trabajamos con fecha y hora es determinar el formato empleado por el manejador de base de datos. Sin embargo, esto ya no ser谩 m谩s problema con @Temporal.

Mediante el uso de @Temporal es posible determinar si nuestro atributo almacena Hora, Fecha u Hora y fecha, y es posible utilizar la clase Date o Calendar para estos fines. Yo siempre recomiendo utilizar Calendar, pues tiene muchas m谩s operaciones para manipular fecha y hora.

Se pueden establecer tres posibles valores para la anotaci贸n:

  • DATE: Acotara el campo solo a la Fecha, descartando la hora.
    • @Temporal(TemporalType.DATE)
  • TIME: Acotara el campo solo a la Hora, descartando a la fecha.
    • @Temporal(TemporalType.TIME)
  • TIMESTAMP: Toma la fecha y hora.
    • @Temporal(TemporalType.TIMESTAMP)

as

JPA y los m茅todos hashCode & equals

Tutorial de JPA persistence.xmlPor defecto, todos los objetos en Java heredan de la case Object los m茅todos hashCode y equals los cuales sirvan para identificar si dos variables hacen referencia al mismo objeto.
El comportamiento de facto del m茅todo hashCode retorna la posici贸n en memoria de un objeto, y el m茅todo equals compara el hashCode de los dos objetos evaluados, de esta forma, si las dos variables hacen referencia a la misma posici贸n de memoria, entonces se dice que son igual, de lo contrario son diferentes.
En el caso de las Entidades, la implementaci贸n default de estos m茅todos no funciona correctamente, debido a que una Entidad de dice que es igual a otra si se cumplen dos condiciones:

鈥 Los dos objetos son de la misma clase.
鈥 El valor de su ID (@Id) son iguales

Si estas dos condiciones se cumplen entonces las dos entidades son iguales sin importar que no hagan referencia a mismo objeto en memoria. Debido a esto, es que es importante sobrescribir estos dos m茅todos para que eval煤en a una Entidad por las dos condiciones mencionadas.

Implementando los m茅todos hashCode & equals

Algo que me ha llamado mucho la atenci贸n es que a pesar de que estos dos m茅todos son b谩sicos y que se utilizan con regularidad, muchas personas no entienden como trabajan internamente y a煤n menos como sobrescribirlos correctamente, si eres una de esas personas, no te preocupes ya que los IDE鈥檚 ya tiene por default utilidades que nos ayudan a generarlos de forma adecuada.
Lo primero que haremos ser谩 abrir la entidad Employee que hemos venido trabajando a lo largo de este tutorial. Luego presionaremos Source > Insert Code del men煤 principal, esto arrojara una peque帽a lista de acciones, seleccionamos la opci贸n equals() and hashCode(). Nos arrojara una pantalla como la siguiente:
M茅todo equals y hashcode as

Mapeo de enumeraciones con @Enumerated

Tutorial de JPA @EnumeratedUna de las ventajas de utilizar enumeraciones en Java, es podemos limitar los valores posibles para una propiedad, forzando a los desarrolladores a utilizar los valores ya definidos y evitando el margen de error.

@Enumerated

Con JPA tambi茅n es posible utilizar enumeraciones y pueden ser de mucha ayuda para asegurar que los programadores persistan un valor v谩lido dentro de una lista previamente definida. JPA nos permite mediante la anotaci贸n @Enumerated definir la forma en que una enumeraci贸n ser谩 persistida, las cuales se explican a continuaci贸n:

  • String: permite persistir la enumeraci贸n por su nombre, lo que significa que ser谩 una columna alfanum茅rica. La anotaci贸n quedar铆a as铆:
    • @Enumerated(value = EnumType.STRING)
  • Ordinal: esta estrategia persiste un valor entero que corresponde al valor ordinal o posici贸n de valor en la enumeraci贸n. La anotaci贸n quedar铆a de la siguiente manera:
    • @Enumerated(value = EnumType.ORDINAL)

Retomaremos la entidad Employee que hemos venido analizando en todo este tutorial y le agregaremos una nueva propiedad que corresponda al status:

as