JPA cascade de persister et de références à des détaché entités jette PersistentObjectException. Pourquoi?

J'ai une entité Toto qui fait référence à une entité Bar:

@Entity
public class Foo {

    @OneToOne(cascade = {PERSIST, MERGE, REFRESH}, fetch = EAGER)
    public Bar getBar() {
        return bar;
    }
}

Lorsque je persiste un nouveau Foo, il peut obtenir une référence à un nouveau Bar ou dans un Bar. Quand il arrive un existant Bar, qui se trouve être détaché, mon fournisseur JPA (Hibernate) jette l'exception suivante:

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

Quand je l'ai assurez-vous que la référence à la Bar est réussi (ci-joint) ou quand je omettre la cascade de PERSISTER dans la relation, tout fonctionne bien.

Ni solution est cependant 100% satisfaisante. Si je retire la cascade persistent, évidemment je ne peux pas conserver un Foo avec une référence à une nouvelle Barre de plus. De renvoi de Barre réussi nécessite un code comme celui-ci avant de la persistance:

if (foo.getBar().getID() != null && !entityManager.contains(foo.getBar())) {
foo.setBar(entityManager.merge(foo.getUBar()));
}
entityManager.persist(foo);

Pour une seule Barre cela pourrait ne pas sembler une grosse affaire, mais si je dois prendre tous en compte les propriétés des comme ça, je vais finir avec assez horrible code qui semble à la défaite de la raison de l'utilisation de l'ORM en premier lieu. Je pourrais aussi bien persister mon objet graphique manuellement à l'aide de JDBC de nouveau.

Lorsque compte tenu de l'actuelle référence de la Barre de la seule chose JPA a à faire est de prendre son ID et l'insérer dans une colonne de la table qui contient Foo. C'est exactement ce que lorsque la Barre est attaché, mais lève l'exception lorsque la Barre est détachée.

Ma question est; pourquoi faut-il le Bar pour être fixé? Sûrement son ID ne change pas lors de l'occurrence de la Barre des transitions de détaché, attaché de l'état, et que l'ID semble être la seule chose nécessaire ici.

Est-ce peut-être un bug en mode veille prolongée ou ai-je raté quelque chose?

  • Vous pouvez supprimer PERSISTENT en cascade, et le check if (id == null) { em.persiste(foo.getBar ()) }, Au moins il rend votre si de plus simple.
  • Vrai, ce serait en effet, il est un peu plus simple. Merci pour la suggestion.
  • Bien sûr, même avec un peu plus simple si les déclarations, la persistance de code serait encore à marcher à travers la totalité de l'objet graphique, qui est quelque chose que je suis désespérément essayer de les éviter.
InformationsquelleAutor Arjan Tijms | 2010-11-28