Operaciones CRUD con JPA en Java

Resumen

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_sql en true dentro 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:

  1. em.getTransaction().begin para iniciar la transacción.
  2. em.persist(newEmployee) para guardar la nueva entidad.
  3. 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.