2009-11-23 18 views
8

estamos utilizando la implementación Toplink de JPA + Spring + EJB. En uno de nuestros EJB tenemos algo como esto:JPA - guardar cambios sin persist() invocado

public void updateUser(long userId, String newName){ 
    User u = em.get(User.class, userId); 
    u.setName(newName); 
    // no persist is invoked here 
} 

Así que, básicamente, se supone que este método updateUser para actualizar el nombre de usuario con ID dado. Pero el autor de este método olvidó invocar em.persist (u);

Y lo más extraño es que funciona bien. ¿Cómo puede ser? Estaba 100% seguro de que sin invocar em.persist() o em.merge() no hay forma de que los cambios pudieran haberse guardado en la base de datos. ¿Podrían? ¿Hay algún escenario cuando esto podría suceder?

Gracias

Respuesta

11

Estás trabajando con una entidad administrada. Si la entidad no se desconecta debido a que su administrador de entidades está cerrado, todos los cambios hechos a la entidad se reflejan en la base de datos cuando la sesión se vacía/se cierra y la transacción se compromete.

Desde el Java EE tutorial:

El estado de entidades persistente es sincronizada con la base de datos cuando la transacción con la que la entidad es commit asociados.

Editar para mayor claridad y explicación: Así que hay tres modos distintos que una entidad podría estar durante su ciclo de vida:

  • Unsaved: La entidad ha creado una instancia, pero persist() no tiene sido llamado todavía
  • Administrado: La entidad se ha conservado usando persist(), o cargada desde la base de datos, y está asociada con una sesión de administrador de entidades. Todos los cambios en la entidad se reflejan en la base de datos cuando se vacía la sesión del administrador de la entidad.
  • Separado: Se cerró la sesión del administrador de entidades de la entidad. Los cambios en la entidad no se reflejarán en la base de datos automáticamente, pero se pueden combinar de forma explícita con el comando merge().
+0

Gracias. ¡Esto ayudó mucho! Siempre pensé que se requiere invocar em.persist(), incluso si el objeto está asociado con EntityManager actual. – anthony

+0

Extraño: en mi configuración, tengo una referencia a una entidad administrada. Luego cambio el estado de esta entidad. Luego llamo 'entityManager.flush()'. En caso de que esto se ejecute dentro de una transacción, entonces el estado ** modificado de la entidad se escribe ** en la base de datos. En caso de que esto se esté ejecutando sin una transacción, entonces el estado ** modificado de la entidad no se escribe ** en la base de datos. Entonces, ¿la siguiente afirmación es verdadera ?: * "Siempre tiene que haber una transacción comprometida o una llamada a' entityManager.persist (obj) 'para escribir el último estado de' obj' en la base de datos. "* .... (Estoy usando JPA 2.0 con Hibernate (4.1.7.Final)) – Abdull

+0

@Abdull, sí, la especificación JPA no define ningún comportamiento de autocommit, por lo que necesita una transacción en curso o nada se escribe en absoluto en la base de datos. – Henning

Cuestiones relacionadas