que tienen una entidad Foo que hace referencia a una barra de entidad:La cascada de JPA persiste y las referencias a entidades separadas arrojan PersistentObjectException. ¿Por qué?
@Entity
public class Foo {
@OneToOne(cascade = {PERSIST, MERGE, REFRESH}, fetch = EAGER)
public Bar getBar() {
return bar;
}
}
Cuando persisto un nuevo Foo, se puede obtener una referencia a un nuevo bar o un bar existente. Cuando se pone una barra existente, que pasa a ser individual, el profesional de la APP (Hibernate) lanza la siguiente excepción:
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.example.Bar
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:102)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:636)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:628)
at org.hibernate.engine.EJB3CascadingAction$1.cascade(EJB3CascadingAction.java:28)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:291)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:239)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:192)
at org.hibernate.engine.Cascade.cascade(Cascade.java:153)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:454)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:49)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:154)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:110)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:645)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:619)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:623)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:220)
... 112 more
Cuando sea asegúrese de que la referencia a la barra es administrado (adjunto) o cuando Omito la cascada PERSIST en la relación, todo funciona bien.
Ninguna solución, sin embargo, es 100% satisfactoria. Si elimino la cascada, obviamente no puedo persistir un Foo con una referencia a un nuevo Bar más. Haciendo referencia a la barra logró requiere un código como éste antes de la persistencia:
if (foo.getBar().getID() != null && !entityManager.contains(foo.getBar())) {
foo.setBar(entityManager.merge(foo.getUBar()));
}
entityManager.persist(foo);
Para una sola barra que esto podría no parecer una gran cosa, pero si tengo que tomar todas las propiedades en cuenta como esto voy a terminar con un código bastante horrible que parece frustrar la razón de usar ORM en primer lugar. También podría bien persistir mi gráfico de objetos manualmente usando JDBC nuevamente.
Cuando se le presente una referencia de Barra existente, lo único que tiene que hacer JPA es tomar su ID e insertarla en una columna de la tabla que contiene Foo. Hace exactamente esto cuando Bar está conectado, pero arroja la excepción cuando se separa la barra.
Mi pregunta es; ¿Por qué necesita que se adjunte Bar? Seguramente su ID no cambiará cuando la instancia de Bar pase del estado separado al adjunto, y ese ID parece ser lo único que se necesita aquí.
¿Es esto quizás un error en Hibernate o me falta algo?
Puede eliminar PERSIST de la cascada, y verificar si (id == null) {em.persiste (foo.getBar())} Al menos hace su if simplier. – amorfis
Cierto, eso de hecho lo haría un poco más simple. Gracias por la sugerencia. –
Por supuesto, incluso con sentencias if ligeramente más simples, el código persistente aún tendría que recorrer todo el gráfico del objeto, lo cual es algo que intento desesperadamente evitar. –