EntityManager y el archivo persistence.xml

Tutorial de JPA persistence.xmlEn esta sección hablaremos de cómo crear el archivo persistence.xml y como establecer conexión con la base de datos. Cabe mencionar que para fines de practicidad estaremos trabajando con MySQL, el Gestor de bases de datos relacional más popular del mundo y que además tiene una versión gratuita, por lo cual será necesario que descarguemos e instalemos MySQL, así como el cliente workbench que los puedes descargar directamente desde la página oficial de MySQL.

Creación del archivo Persistence.xml

Una vez instalado MySQL procederemos a la creación del archivo persistence.xml, para lo cual seleccionaremos la opción File > New File y aparecerá la siguiente pantalla; en ella ubicamos la categoría Persistence y luego el archivo Persistence Unit, tal como aparece en la imagen:

persistence.xml - file

Presionamos Next y nos arrojara una nueva pantalla, en esta definimos el nombre de la unidad de persistencia, la implementación de JPA, la conexión a la base de datos y la estrategia de generación de las tablas.

Más adelante analizaremos las unidades de persistencia y las estrategias de generación de las tablas, por el momento solo será necesario prestar atención en el nombre con el que crearemos la unidad de persistencia y la configurar la conexión a la base de datos, llenemos el formulario como en la siguiente imagen:

persistence.xml - new connection

Finalmente será necesario crear la conexión a la base de datos, para esto seleccionaremos el campo Database Connection y seleccionaremos la opción New Database Connection, esto nos arrojará una nueva venta donde deberemos seleccionar el driver de MySQL tal como aparece en la siguiente imagen:

persistence.xml - jdbc driver

Presionamos en el botón Next y nos arrojara una nueva pantalla donde definiremos los datos de conexión a la base de datos, para esto deberíamos tener ya creada una base de datos llamada JPATutorial y tener acceso a ella por medio de un usuario de MySQL, en mi caso, cree un usuario llamado JPA, pero tu podrías utilizar el root o cualquier otros, lo importante es que exista una base de datos donde podremos crear tablas y realizar las operaciones básicas sobre ellas. Una vez definidos los datos de conexión presionaremos Test Connection para asegurar que la conexión a la base de datos fue exitosa y presionamos Finish. Esta acción nos regresara a la pantalla anterior donde nuevamente presionaremos Finish. Esto concluirá con la generación del archivo.

Un detalle sumamente importante acerca de este archivo es que debe estar en la carpeta META-INF  , de lo contrario no será localizado cuando el API de JPA inicie.

NetBeans nos da la opción de manipular el archivo persistence.xml de forma gráfica y en texto plano, por lo cual abriremos el archivo y en la parte superior cambiaremos del modo Design al modo Source para analizar su contenido:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="JPA_PU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/JPATutorial?zeroDateTimeBehavior=convertToNull&amp;serverTimezone=UTC"/>
      <property name="javax.persistence.jdbc.user" value="jpa"/>
      <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
      <property name="javax.persistence.jdbc.password" value="1234"/>
      <property name="javax.persistence.schema-generation.database.action" value="create"/>
    </properties>
  </persistence-unit>
</persistence>

Por el momento pongamos foco en el nombre de la unidad de persistencia, en este caso llamada JPA_PU  , seguido veamos que en la sección de properties se encuentran todos los datos de conexión a la base de datos, como el driver, cadena de conexión, usuario y password, los cuales serán cargados en tiempo de ejecución para establecer la conexión a la base de datos. Finalmente veamos la última propiedad schema-generation.database.action con un valor de create,  esta propiedad es la estrategia para la generación de las tablas, lo que quiere decir que JPA creara de forma automática todas las tablas requeridas de forma automática mediante la definición de las Entidades. Más adelante analizaremos las ventajas de esta propiedad.

NOTA: En algunas versiones de MySQL es requerido agregar el parámetro &amp;serverTimezone=UTC al final de la línea 6. Al final de esta sección ejecutaremos la aplicación, si por alguna razón te sale un error, intenta agregar este parámetro. En caso de no funcionar puedes escribirme el error en los comentarios.

Introducción a la clase EntityManager

JPA tiene como interface medular al EntityManager, el cual es el componente que se encarga de controlar el ciclo de vida de todas las entidades definidas en la unidad de persistencia, y es mediante esta interface que se pueden realizar las operaciones básicas de una base de datos, como consultar, actualizar, borrar, crear (CRUD). También es la clase por medio de la cual se controlan las transacciones.

Los EntityManager son configurados siempre a partir de las unidades de persistencia definidas en el archivo persistence.xml y es posible crearlas de dos formas las cuales dependerán del tipo de aplicación:

  • Aplicación de escritorio: En el caso de ejecutar nuestro programa como una aplicación de escritorio o stanalone será necesario instanciar el EntityManager a través de la clase EntityManagerFactory. En la primera parte de este tutorial estaremos utilizando este método. Un detalle importante de este método es que el programador es el responsable de abrir y cerrar las transacciones.
  • Aplicaciones Empresariales: Cuando nuestra aplicación vive dentro de una Application Server o precisamente en un EJB Container, los EntityManager se referencia por medio de Inyección de dependencias (CDI), utilizando la anotación @PersistenceContext , de este modo, el Application Server es el encargado de la creación de los EntityManager para su inyección. Un detalle interesante de este método es que el Application Server se puede encargar de forma automática de las transacciones, abriendo una transacción al inicio de la ejecución de un método de negocio y cerrando la transacción automáticamente al finalizar la invocación del método. Más adelante analizaremos este método.

Cabe mencionar que JPA está íntimamente relacionado en la especificación de EJB 3.X, por lo que JPA toma más sentido cuando lo utilizamos en entornos empresariales, sin embargo, al inicio de este tutorial empezaremos utilizándolo en aplicaciones de escritorio, debido a que es mucho más fácil, sin embargo, a medida que avancemos nos iremos aventurando a utilizar JPA en aplicaciones empresariales.

Instanciando un EntityManager

Como a lo largo de este tutorial esteremos instanciando frecuentemente al EntityManager crearemos una clase genérica que estaremos reutilizando a lo largo de todo el tutorial.

Creemos una nueva clase llamada EntityManagerUtil dentro del paquete com.obb.jpa.jpaturorial.util que deberá de quedar de la siguiente manera:

package com.obb.jpa.jpaturorial.util;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 * @author Oscar Blancarte
 */
public class EntityManagerUtil {
    
    public static EntityManager getEntityManager(){
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("JPA_PU");
        EntityManager manager = factory.createEntityManager();
        return manager;
    }
    
    public static void main(String[] args) {
        EntityManager manager = EntityManagerUtil.getEntityManager();
        System.out.println("EntityManager class ==> " + manager.getClass().getCanonicalName());
    }
}

Entendamos que está pasando, en la línea 13 se obtiene una instancia de la Interface EntityManagerFactory, mediante la clase Persistence, esta última recibe como parámetro el nombre de la unidad de persistencia que definimos en el archivo persistence.xml. una vez con el EntityManagerFactory se obtiene una instancia de EntityManager para finalmente ser retornada para ser utilizada.

Una de las cosas interesantes de JPA es que es una especificación por tal motivo no existe como tal una implementación única, es por eso que el EntityManagerFactory tiene la responsabilidad de obtener la implementación concreta del EntityManager provista por el proveedor. Por lo que la clase concreta devuelta por el método createEntityManager del EntityManagerFactory dependerá completamente de la implementación de JPA que estemos utilizando en nuestra unidad de persistencia. Regresando un poco al archivo persistence.xml podremos ver que existe la siguiente línea:

<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

Esta línea le dice al EntityManagerFactory con que proveedor estamos trabajando de tal manera que, si el día de mañana decidimos trabajar con un proveedor distinto a EclipseLink, tan solo tendremos que definir la clase de la nueva implementación de JPA.

Comprender exactamente cómo funciona la clase EntityManagerFactory requiere conocer cómo funciona el patrón de diseño Abstract Factory, el cual se explica perfectamente en mi libro.

Una vez explicado la forma de obtener en EntityManager procederemos, para lo cual solo será necesario ejecutar el proyecto, te preguntará si quieres establecer la clase EntityManagerUtil como clase principal del proyecto, seleccionamos que sí y el programa iniciará con la ejecución, si todo sale bien, entonces tendrás una salida como la siguiente:

EntityManager class ==> org.eclipse.persistence.internal.jpa.EntityManagerImpl
------------------------------------------------------------------------
BUILD SUCCESS

Este punto es crucial para muchas personas, debido a que mucha gente no logra configurar el EntityManager y mueren en el intento, si por alguna razón el programa no te funciona, recuerda que me puedes enviar un comentario al final de este artículo, a si te puedo ayudar a encontrar el problema.

Tambíen los quiero invitar a ver mi curso de JPA, donde explico todos estos temas aplicados con API REST, https://codmind.com/courses/jpa

Los invito a mi Curso de Mastering JPA, donde habla de todos estos temas y crearemos un API REST para probar todos los conceptos de persistencia.

Finalmente, observemos que en la salida existe una línea que dice EntityManager class ==> org.eclipse.persistence.internal.jpa.EntityManagerImpl , esto representa la clase real del EntityManager que creo el EntityManagerFactory. Con esto podemos dar por concluida la configuración del EntityManager y de la Unidad de persistencia, en el siguiente topico hablaremos hacerca de la Entidades, que son y como crearlas.

NOTA: Este artículo es solo una sección del Tutorial de JPA, para ver el contenido completo de este tutorial regresa al Índice en el botón de abajo.


AnteriorÍndiceSiguiente 

21 thoughts to “EntityManager y el archivo persistence.xml”

  1. Oscar buenas tardes mi hermano.
    Si por alguna razon alguien no logra configurar la EntityManager, es posible que se por los siguiente, resulta que al crear el archivo de persistence.xml, la configuracion por default de la linea 6 es
    name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/JPATutorial?zeroDateTimeBehavior=convertToNull"

    por consiguiente es bueno acotar que al final de esta liena hay que agregar &serverTimezone=UTC para que este sea igual a ejemplo acá expuesto, ya que por alguna razón da error.

    1. Hola Arquímedes, Tienes razón, al parecer en las últimas versiones de MySQL está solicitando este parámetro adicional. No recuerdo que, en versiones anteriores fuera requerido, pero que bueno que lo comentas, voy actualizar el tutorial para que haga mención a esto.
      Gracias por el aporte, te mando un abrazo.

      NOTA: Verás que junte tus dos comentarios en uno solo, así quedará más claro para el resto

  2. Hola
    En el apartado
    New Persistence Library.- – >Provider and Database –> Persistece Library – – EclipseLink (JPA 2.1)
    hay algún modo de cambiar EclipseLink por otra libreria que implementa JPA 2.2
    Lo he intentando desplegando el list box y eligiendo la option new Persistecen Library, pero no he logrado que la nueva librería sea añadida al list box
    Saludos

    1. Hay dos formas si mal no recuerdo, la primera, te debe de de decir a un lado, instalar nueva librería o algo así, la otra, es que ese listado se llena en función del servidor de aplicaciones que tienes, pues detecta la implementación de JPA que utiliza por default.

      1. Gracias por su respuesta, a lo q hago referencia es q en el persistence.xml pueda indicarle q las configuraciones estan en un .proeprties para poder hacer cambios en caliente sin necesidad de generar un war nuevamente

        1. De forma nativa no lo puedes hacer, pero lo puedes hacer con algún plugin de Maven que remplace las cadenas el momento de compilar, o incluso, podrías usar Jenkins para hacer el reemplazo antes de desplegar.

  3. Hola, una pregunta estoy tratando mapear una clase usando el EclipseLink pero al momento de Ejecutar me sale esto
    “[EL Warning]: metamodel: 2020-06-19 20:43:24.572–The collection of metamodel types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units. Please verify that your entity classes are referenced in persistence.xml using either elements or a global false element”

    y no me crea la tabla en mis base de Datos.

  4. Al utilizar Netbeans 11, en la parte de la Persistence Library no viene cargado ninguno para crear la persistencia, ni el conector, como es posible que tome los que tenemos declarados en el Maven. Saludos y se ve muy interesante su material.

    1. No recuerdo los pasos exactos en Netbeans, pero lo que puedes hacer es tomar la implementación generica de JPA, es decir sin ninguna implementación en concreto, y luego en runtime de las provees por Maven.

  5. como se haces esto
    si trabajas con eclipselink java y netbeans
    para mi jpa y varios jsp como el principal index login usuario etc
    porque me salta error porque no reconoce javax.persistence.Persistence.create entity manager (persistence: 84 54

    1. Para cambiar de implementación tienes que cambiar la clase que se define en el tag , la clase concreta la tendrás que revisar en la documentación de cada proveedor.

    1. Hola Dario, veo que tienes demaciada dudas sobre JPA, lo que te ofresco es que te suscribas a mi curso de Mastering JPA para que te enseñe todo lo referente a esta tecnología, y de esta forma te puedo ayudar en cosas mas puntuales.
      El curso lo podrás encontrar https://codmind.com/courses/jpa, además esta con descuento del 40% por el black friday

      saludos.

Deja un comentario

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