Paul Flores
Andres Otavo
Paul Flores
Si trabajas con Java y necesitas conectar tu aplicación a una base de datos sin escribir SQL plano por todos lados, JPA es tu mejor aliado. Con JPQL, EntityManagerFactory y EntityManager puedes ejecutar operaciones de persistencia de forma estructurada y limpia, ideal para desarrolladores backend que quieren dominar el mapeo objeto-relacional.
¿Qué es JPQL y en qué se diferencia de SQL?
JPQL es el lenguaje de consultas que usas dentro de JPA para hacer operaciones de persistencia sobre tus entidades, no directamente sobre tablas. Se parece mucho a SQL, pero opera sobre objetos Java mapeados.
¿Qué es JPQL? Es un lenguaje de consultas orientado a objetos que permite buscar, insertar, actualizar o eliminar entidades Java. A diferencia de SQL, no consultas tablas sino clases mapeadas como entidades.
Esa diferencia cambia tu forma de pensar las consultas: en lugar de pedirle datos a una tabla, le pides instancias a una entidad.
¿Para qué sirven EntityManagerFactory y EntityManager?
Dentro de la configuración de JPA aparecen dos piezas clave que conviene entender desde el inicio [1:00]. EntityManagerFactory funciona como la puerta de entrada a tu base de datos, mientras que EntityManager es la unidad de trabajo donde ejecutas tus operaciones de persistencia.
Los métodos principales que usarás con EntityManager son:
find: busca una entidad por su identificador único.persist: guarda una nueva entidad en la base de datos.merge: combina cambios de una entidad gestionada, funciona como actualización.remove: elimina una entidad existente.createQuery: ejecuta una consulta personalizada en JPQL.getTransaction: obtiene la transacción actual del EntityManager.Con estos seis métodos cubres prácticamente todo el ciclo CRUD.
¿Cómo se mapea una entidad Employee con anotaciones JPA?
Después de tener listo el POM con los conectores de MySQL, Java Persistence e Hibernate, y el archivo persistence.xml configurado, toca crear la entidad [2:30]. La clase Employee se ubica dentro del paquete entity e incluye los campos id, firstName, surname, moreSurname, email y salary, junto con sus getters, setters, constructores y método toString.
Las anotaciones que dan vida al mapeo son:
@Entity: marca la clase como entidad gestionada por JPA.@Table(name = "employees"): define el nombre de la tabla en la base de datos.@Id: indica cuál atributo es la llave primaria.@GeneratedValue(strategy = GenerationType.IDENTITY): configura el id como autoincremental.@Column(name = "firstname"): enlaza el atributo Java con el nombre real de la columna cuando difieren.GenerationType.IDENTITY es el que usas cuando tu base de datos maneja autoincremental por sí sola, no el primer valor del enum.
¿Cómo se construye la clase UtilEntity?
Dentro de un paquete util creas la clase UtilEntity, que centraliza la fábrica de EntityManager. Dentro declaras un private static final EntityManagerFactory inicializado con el método privado buildEntityManagerFactory, que retorna Persistence.createEntityManagerFactory("MyPersistenceUnit").
El nombre que pases ahí debe coincidir exactamente con el que definiste en tu persistence.xml. Después agregas un public static EntityManager getEntityManager que retorna entityManagerFactory.createEntityManager. Así, cada vez que necesites una unidad de trabajo, la pides desde un solo punto.
¿Cómo ejecutar las operaciones CRUD con JPA paso a paso?
Con todo configurado, el archivo main se vuelve el laboratorio para probar cada método [7:00]. Empiezas instanciando el EntityManager con UtilEntity.getEntityManager y desde ahí ejecutas las cuatro operaciones básicas.
¿Cómo listar y buscar registros con createQuery y find?
Para listar todos los empleados usas createQuery con la sentencia JPQL select e from Employee e, indicando además Employee.class como segundo parámetro y llamando a getResultList. El resultado lo recorres con un forEach para imprimirlo.
¿Cómo activo los logs SQL en Hibernate? Agrega la propiedad
hibernate.show_sqlentruedentro de tu persistence.xml. Esto imprime en consola las consultas SQL que Hibernate genera por debajo, útil para depurar.
Para buscar un registro específico, declaras un int employeeId con el valor a buscar y llamas a em.find(Employee.class, employeeId). Si existe, te devuelve la entidad lista para usar; en la prueba aparece Michael Johnson como resultado del id 3.
¿Cómo crear y actualizar registros con persist y merge?
Para crear un empleado instancias new Employee, llenas sus setters con firstName, surname, moreSurname, email y salary, y luego ejecutas la secuencia transaccional:
em.getTransaction().begin para iniciar la transacción.em.persist(newEmployee) para guardar la nueva entidad.em.getTransaction().commit para confirmar el cambio.Si olvidas el begin, recibes la excepción Transaction not successfully started, un error muy típico al empezar con JPA [13:30]. Tras correrlo correctamente, el nuevo empleado se guarda con id 6 y Hibernate muestra el insert por debajo.
La actualización sigue el mismo patrón pero con merge. Primero buscas la entidad con find, modificas los campos con sus setters (por ejemplo, cambiar firstName a Irving Juárez y salary a 97000), y luego ejecutas begin, em.merge(employeeToUpdate) y commit. Puedes verificar el cambio directamente en MySQL Workbench haciendo select rows sobre la tabla.
¿Cómo eliminar registros con el método remove?
La eliminación tiene un detalle importante: necesitas pasar la entidad encontrada, no solo su id. El flujo correcto es declarar int employeeToDelete con el id, ejecutar em.find(Employee.class, employeeToDelete) y guardar el resultado en una variable Employee.
Después inicias la transacción con begin, ejecutas em.remove(employee) pasando la entidad completa, haces commit y cierras con em.close. Si pasas solo el id en lugar de la entidad, el remove falla y el registro no se elimina.
Una vez ejecutado correctamente, Hibernate muestra el delete from employees where id, y al revisar la base de datos confirmas que el registro desapareció.
¿Qué método de JPA te gustaría profundizar primero en tu próximo proyecto? Comenta tu caso de uso.
Paul Flores
Andres Otavo
Paul Flores
Carlos Rafael Reyes Jiménez
Isay Humberto Lucas Hernandez
Jhon Carlos Romo Ramirez
Sergio Andrés Majé Franco
José Antonio Alcántara Rosales
Gerardo Daniel Rodriguez Mariscal
Rafael Camacho
Eisten Eisten
Tara Campos Padilla
Raul Cabrera
Daniel Esteban Pérez Bohórquez
Victor Ovalle Porras
Daniel Esteban Pérez Bohórquez
Zvonko Pino
ALVARO ZENON QUISPE SEGALES
Ana Fernanda Gutierrez Villanueva
ProfesorDaniel Esteban Pérez Bohórquez
eduardo montaño cardenas
eduardo montaño cardenas
ANDRES ALFONSO MIRA MEJIA
Xavier Armando Larios Alvarenga
Xavier Armando Larios Alvarenga
Jorge Mario Florez Hernández
José Fretel
Platzi
Jose Luis Jauregui
Gabriel Omar Gramajo
Si a ustedes les falla algo... Una opción que me funcionó a mí es usar exactamente la misma versión de Hibernate que usa Ana, la cual es la 5.5.7.Final. De esa forma me dejó listar cerca del minuto 15.
De la misma manera les comparto un articulo que encontré, el cual habla de soluciones comunes a algunos problemas
Link
Muchas gracias por el aporte, solucione el problema con la ultima opcion del link que compartes: Me aparecia error de que no encontraba un provider valido para unidad de persistencia, tuve que quitar la etiqueta <type>pom</type> de la dependencia de hibernate en el archivo POM
¡Un gusto poderte ayudar!
si les da problemas, son por las nuevas métricas que deben tener en el persistence.xml, acá les dejo mi pom.xml y persistence.xml, estamos a 25/10/2023.
¡Muchísimas gracias tu aporte hizo el truco!
Bravo!
Debido a las migraciones de los artifacs javax persistence a jakarta persistence api e hibernate core, el código del tutorial hay que hacerle pequeños cambios para que funcione.
pom.xml
persistence.xml
El resto es cambiar en los import javax por jakarta
Muchas gracias Sergio.
Definitivamente se han deshabilitado versiones anteriores, porque probé con las otras soluciones y no funciona.
Algo muy "tonto", tal vez, creo yo. Y que tarde bastante tiempo en darme cuenta, es que en
List<Employee> employees = em.createQuery("SELECT e FROM Employee e",Employee.class).getResultList(); ```Mas especificamente en: "SELECT e FROM Employee e" el "Employee" debe ser el nombre de la clase y no el nombre de la tabla en la mysql. Al asimilarse mucho a un query me confundi y puse el nombre de la tabla, por ende me daba error. Truchas con eso.
Yo lo quise probar con las dependecias mas recientes y me daba este error " jakarta Unrecognized JPA persistence.xml XSD version : '3.2' "
Lo arreglé cambiando los archivos de esta manera:
pom.xml
persistence.xml
Muchas gracias por el comentario, me has ahorrado mucho tiempo
Como resulta que la librerias Javax fueron relocated por las Jakarta, yo configure con este así como los últimos Hibernate, coloco la configuración como me funcional hasta el momento:
Tambien tengo la conexión a una BD Mysql de AWS RDS:
El resto todo es igualito hasta ahora.
Tengo el error de "Could not resolve root entity 'Employee'", alguien tuvo el mismo problema? ayuda por favor
sept 25, 2023 10:17:01 P. M. javax.persistence.spi.PersistenceProviderResolverHolder$DefaultPersistenceProviderResolver log WARNING: javax.persistence.spi::No valid providers found. Exception in thread "main" java.lang.ExceptionInInitializerError at org.example.platzi.Main.main(Main.java:13) Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named myPersistenceUnit at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:86) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55) at org.example.platzi.Util.UtilEntity.buildEntityManagerFactory(UtilEntity.java:11) at org.example.platzi.Util.UtilEntity.<clinit>(UtilEntity.java:9) Alguna suposición de lo que puede ser?
Hola tenia el mismo Warning; en el archivo de pom.xml use la misma dependencia del curso y se soluciono:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.5.7.Final</version> </dependency>ha funcionado victor gracias por tu respuesta
chicos si muchos tuvieron problemas con lo de JPA se puede lograr lo mismo que hace la profe pero usando esta dependencia
<dependency> <groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> <version>3.1.0</version> </dependency>
otros usan esta dependencia para JPA:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>es lo mismo?
La dependencia que mencionas se llama spring-boot-starter-data-jpa y es parte del ecosistema de Spring Boot. La elección de las dependencias dependerá de los requisitos del proyecto y preferencias 😊.
Si alguno no le llega a funciona como fue mi caso y me demore dandome tiempo, el truco esta aca, el código de persistence.xml de la clase pasada es distinto a la de esta clase.. el de la anterior clase es <persistence xmlns=".... version="2.2">, pero debemos cambiarlo por <persistence xmlns="..." version="2.2"> ME TOCO PONER 3 PUNTOS por que no me dejan subir enlaces a la zona de aportes, si alguien tambien me comenta porque se hace este cambio ??
aclaro que tuve que agregar la S en persistencexmlns porque no me dejaba subirlo
solucion usar dependencia de jakarta en vez de javax
✅
Para modificar la etiqueta <class> en el archivo persistence.xml con dos entidades, debes agregar ambas entidades de la siguiente manera:
<class>org.example.platzi.entity.Employee</class> <class>org.example.platzi.entity.AnotherEntity</class>
Cada entidad debe estar definida en su propia línea dentro de la etiqueta <persistence-unit>. Esto le indica a JPA que hay más de una entidad a gestionar en tu aplicación. Si tus entidades están en paquetes diferentes, asegúrate de incluir la ruta completa en cada etiqueta <class>.
Recuerda que es importante que las entidades estén correctamente anotadas con @Entity.
La clase UtilEntity en el contexto de JPA y EntityManager se utiliza para gestionar la creación de instancias de EntityManager. En el transcript se menciona que se crea un método privado estático buildEntityManagerFactory que devuelve una instancia de EntityManagerFactory, utilizando el nombre de la unidad de persistencia definida en un archivo persistence.xml.
Este enfoque permite que EntityManagerFactory actúe como una puerta de acceso a la base de datos, y el método getEntityManager se utiliza para obtener el EntityManager que manejará las operaciones CRUD.
Este patrón asegura un manejo eficiente de los recursos de la base de datos.
Para los que estén probando la conexión a DB en el minuto 14:40 y no les funciona y obtienen el error:
Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named myPersistenceUnit
Solo deben seleccionar la versión 5.5.7.Final de hibernate-core, como en el video y su el error será solucionado.
no era Hibernate?
Sí, el curso se enfocó en el manejo de la persistencia de datos utilizando Java, pero no se mencionó específicamente Hibernate.
Aquí apuntes para Sql Server, Hibernate 6.5.
implementation("com.microsoft.sqlserver:mssql-jdbc:12.7.0.jre11-preview") implementation("jakarta.persistence:jakarta.persistence-api:3.2.0") implementation("org.hibernate.orm:hibernate-core:6.5.2.Final") ``````js <properties> <property name="jakarta.persistence.jdbc.url" value="jdbc:sqlserver://localhost:1433;databaseName=Northwind;encrypt=false"/> <property name="jakarta.persistence.jdbc.user" value="sa"/> <property name="jakarta.persistence.jdbc.password" value="pruebas123."/> <property name="jakarta.persistence.jdbc.driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/> <property name="hibernate.hbm2ddl.auto" value="none"/> </properties> ``````js import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; public class Factory { private static final EntityManagerFactory emf = buildEntityManagerFactory(); private static EntityManagerFactory buildEntityManagerFactory(){ return Persistence.createEntityManagerFactory("dbcontext"); } public static EntityManager getEntityManager(){ return emf.createEntityManager(); } }
Consulta HQL en Hibernate
em.createQuery("Select e from Employee e", Employee.class).getResultList();
Si quieren entender mas a fondo esa consulta, investiguen sobre HQL en Hibernate.