Managed Entities

Cuando en JPA se hace la operación persist(), una entidad se vuelve Managed, es decir, JPA mantiene registrada la entidad de modo que cualquier cambio que se haga sobre una entidad afecta a lo que existe en la base de datos.

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, uno de los conceptos clave que debemos entender es el de las entidades administradas, o lo que se conoce como entidades managed. Esto significa que el gestor de persistencia, el Entity Manager, tiene registrada la entidad y está atento a cualquier cambio que hagamos sobre ella. No se trata solo de tener un objeto en memoria, sino de contar con un objeto que lleva asociado metadatos y estructuras de control que permiten a JPA detectar modificaciones automáticamente.

Por ejemplo, si tenemos un objeto empleado y llamamos a un método como setApellidos("López"), JPA se da cuenta de ese cambio. Cuando se realiza un commit, la base de datos se actualizará reflejando el nuevo valor, sin necesidad de hacer nada más explícito. Esto es posible porque el método persist convierte un objeto normal en un objeto administrado, es decir, en un objeto que el Entity Manager controla.

Pero no solo persist nos permite trabajar con entidades administradas. Cuando queremos modificar datos que ya existen en la base de datos, podemos usar el método find. Este método nos devuelve una entidad a partir de su clase y su clave primaria, y si la entidad existe, la devuelve en estado administrado. Esto quiere decir que podemos modificar sus atributos directamente y, al hacer commit, esos cambios se reflejarán en la base de datos.

Por ejemplo, si obtenemos un empleado con find y cambiamos su nombre y apellidos, al finalizar la transacción esos cambios se guardarán automáticamente. Sin embargo, si la entidad no existe, find nos devolverá null, por lo que siempre es importante comprobar este caso.

En aplicaciones web, sin embargo, no siempre podemos mantener el Entity Manager abierto durante mucho tiempo. Imaginemos que un usuario está editando un formulario con datos de un empleado y tarda varios minutos en completarlo. No es eficiente ni recomendable mantener la sesión del Entity Manager abierta durante todo ese tiempo, porque consumiría recursos y podría afectar la experiencia de otros usuarios.

Por eso, en muchos sistemas el Entity Manager se crea y destruye con cada petición web. Cuando cerramos el Entity Manager con close, todas las entidades que estaban administradas pasan a estar en estado detaché, es decir, dejan de estar controladas por JPA. Si guardamos un objeto en la sesión del usuario y luego cerramos el Entity Manager, ese objeto ya no está administrado.

Entonces, cuando el usuario envía los cambios para guardar, nos encontramos con que el objeto que tenemos no está en estado administrado. Aquí es donde entra en juego el método merge. Este método acepta una entidad que puede no estar administrada y la combina con el estado actual en la base de datos. Además de hacer un persist si la entidad no existía, merge nos devuelve una nueva instancia que sí está administrada, con la que podemos seguir trabajando.

El proceso de merge consiste en mezclar los estados de la entidad que tenemos con la que está en la base de datos, actualizando los campos que hayan cambiado. Esto es especialmente útil en aplicaciones donde el Entity Manager no está siempre activo, porque nos permite sincronizar los cambios realizados en objetos que estaban en estado detaché.

Es importante no confundir merge con una simple operación de actualización. No es necesario usar merge para modificar entidades que ya están administradas; en esos casos, basta con cambiar sus atributos y hacer commit. Pero si queremos modificar una entidad que no está administrada, merge es la herramienta adecuada para que JPA reconozca y aplique esos cambios.

Para ilustrar estos conceptos, imaginemos un fragmento de código donde primero insertamos un empleado, luego lo obtenemos con find, modificamos sus datos y hacemos commit:

EntityManager manager = entityManagerFactory.createEntityManager();
manager.getTransaction().begin();

// Insertamos un empleado
Empleado empleado = new Empleado();
empleado.setId(10);
empleado.setNombre("Pepito");
empleado.setApellidos("Pérez");
manager.persist(empleado);
manager.getTransaction().commit();

manager.getTransaction().begin();
// Obtenemos el empleado con find
Empleado empleadoModificado = manager.find(Empleado.class, 10);
if (empleadoModificado != null) {
    empleadoModificado.setNombre("David");
    empleadoModificado.setApellidos("López");
}
manager.getTransaction().commit();
manager.close();

En este caso, al modificar empleadoModificado, JPA detecta los cambios porque la entidad está administrada y los guarda automáticamente.

Ahora, si cerramos el Entity Manager y el objeto empleado queda en estado detaché, para actualizarlo necesitamos usar merge:

EntityManager manager = entityManagerFactory.createEntityManager();
manager.getTransaction().begin();

// Supongamos que empleadoDetache es un objeto obtenido previamente y no está administrado
Empleado empleadoDetache = new Empleado();
empleadoDetache.setId(10);
empleadoDetache.setNombre("David");
empleadoDetache.setApellidos("López");

// Usamos merge para actualizar y obtener una entidad administrada
Empleado empleadoManaged = manager.merge(empleadoDetache);

manager.getTransaction().commit();
manager.close();

Aquí, merge sincroniza los cambios de empleadoDetache con la base de datos y nos devuelve una instancia administrada empleadoManaged con la que podemos seguir trabajando si fuera necesario.

En definitiva, entender cuándo y cómo usar persist, find y merge nos permite controlar el ciclo de vida de nuestras entidades en JPA y manejar de forma eficiente las modificaciones en nuestras aplicaciones, especialmente en entornos web donde la gestión de recursos es fundamental.

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