Merge y remove

Cuando una entidad es de tipo detached, las modificaciones a sus campos no alteran la estructura de la base de datos. Es por ello que hay que usar merge para convertirla a una entidad managed. Además, con remove podemos eliminar entidades del sistema por lo que aprovecho para contarlo.

Este curso ha sido marcado como anticuado y no está siendo revisado de forma activa. Es posible que la información pueda estar desactualizada o que los enlaces se hayan roto.

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.

Lista de reproducción
  1. 1
    La persistencia es clave
    6 minutos
  2. 2
    Instalando Hibernate
    8 minutos
  3. 3
    Crear el persistence.xml
    9 minutos
  4. 4
    Construyendo una Entity
    8 minutos
  5. 5
    Accediendo al EntityManager
    9 minutos
  6. 6
    Insertando con persist
    7 minutos
  7. 7
    Managed Entities
    6 minutos
  8. 8
    Merge y remove
    5 minutos
  9. 9
    Inciso sobre Java 8
    7 minutos
  10. 10
    Introducción a relaciones
    6 minutos
  11. 11
    Relación OneToOne
    11 minutos
  12. 12
    OneToOne inverso con mappedBy
    8 minutos
  13. 13
    OneToMany: planteamiento
    6 minutos
  14. 14
    OneToMany: anotaciones
    6 minutos
  15. 15
    OneToMany: EntityManager
    7 minutos
  16. 16
    ¡AYUDA! Error Lazy Initialization (OneToMany)
    5 minutos
  17. 17
    ¡AYUDA! No se fijan las relaciones (OneToMany)
    8 minutos
  18. 18
    Borrar hijos en un OneToMany
    11 minutos
  19. 19
    ON DELETE SET NULL
    8 minutos