Cuando trabajamos con JPA, es fundamental entender la diferencia entre entidades gestionadas (managed) y entidades desconectadas (detached). Una entidad gestionada está asociada a un EntityManager activo, lo que significa que cualquier cambio que hagamos sobre ella se sincroniza automáticamente con la base de datos al confirmar la transacción. En cambio, una entidad detached ya no está vinculada a ningún gestor de entidades, por lo que los cambios que realicemos sobre ella no se reflejarán en la base de datos a menos que la volvamos a asociar.
Para ilustrar esto, imaginemos que tenemos un método que inserta un empleado y luego cierra el EntityManager. En ese momento, la entidad empleado pasa a estar detached. Si intentamos modificar el nombre del empleado después de cerrar el gestor y luego iniciar una nueva transacción con un nuevo EntityManager, esos cambios no se guardarán porque JPA no está gestionando esa instancia.
Aquí un ejemplo simplificado de este comportamiento:
EntityManager man = emf.createEntityManager();
man.getTransaction().begin();
Empleado e = new Empleado();
e.setNombre("Pepito");
man.persist(e);
man.getTransaction().commit();
man.close(); // La entidad 'e' ahora está detached
// Intentamos cambiar el nombre en una nueva transacción
EntityManager man2 = emf.createEntityManager();
man2.getTransaction().begin();
e.setNombre("Dani"); // Cambiamos el nombre en la entidad detached
man2.getTransaction().commit();
man2.close();
En este caso, el cambio a Dani no se reflejará en la base de datos porque e no está gestionada por man2.
Para solucionar esto, JPA nos ofrece el método merge. Este método toma una entidad detached y la vuelve a asociar a un EntityManager, devolviendo una instancia gestionada que refleja los cambios realizados. De esta forma, podemos asegurarnos de que las modificaciones se persistan correctamente.
Podemos usar merge de la siguiente manera:
EntityManager man2 = emf.createEntityManager();
man2.getTransaction().begin();
Empleado eManaged = man2.merge(e); // 'eManaged' es la entidad gestionada
eManaged.setNombre("Dani"); // Cambiamos el nombre en la entidad gestionada
man2.getTransaction().commit();
man2.close();
Incluso si ya hemos modificado la entidad detached antes de hacer el merge, al llamar a merge se sincronizan esos cambios con la base de datos. También es posible llamar a merge sin modificar la entidad, simplemente para reactivar su estado gestionado.
Además de persist y merge, otra operación básica que podemos realizar con el EntityManager es remove, que elimina una entidad de la base de datos en la próxima confirmación de la transacción. Por ejemplo:
EntityManager man = emf.createEntityManager();
man.getTransaction().begin();
Empleado e = man.find(Empleado.class, id);
man.remove(e);
man.getTransaction().commit();
man.close();
Con esto, la entidad Empleado desaparece del sistema.
En resumen, para trabajar correctamente con JPA debemos tener siempre presente si nuestras entidades están gestionadas o no. Si intentamos modificar una entidad detached sin reactivarla con merge o recuperarla con find, los cambios no se guardarán. Por eso, entender y manejar bien estas operaciones básicas es clave para evitar problemas al persistir datos.
Más adelante podemos profundizar en otros aspectos de JPA, como diferentes anotaciones y consultas, pero dominar estas operaciones fundamentales es el primer paso para trabajar con esta tecnología.