objet supprimé serait ré-enregistré en cascade (suppression de l'objet supprimé à partir d'associations)

j'ai les deux entités suivantes:

1 - liste de lecture:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "playlist", orphanRemoval = true, cascade =   CascadeType.ALL)
@OrderBy("adOrder")
private Set<PlaylistadMap> PlaylistadMaps = new HashSet<PlaylistadMap>(0);
  • CascadeType.Tout : est nécessaire pour sauvegarder et mettre à jour sur la collection PlaylistadMap lors de la sauvegarde ou de la mise à jour de l'entité playlist.
  • orphanRemoval = true : est nécessaire pour supprimer l'entité playlist, les références PlaylistadMap doivent être deleteed aussi.

2- PlaylistadMap:

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "fk_playlist", referencedColumnName = "pkid", nullable = false)
private Playlist playlist;

lors de la suppression d'une liste de lecture en utilisant getCurrentSession().delete(); j'obtiens l'exception suivante:

org.springframework.dao.InvalidDataAccessApiUsageException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.xeno.advertisingsuite.web.domain.PlaylistadMap#6]; nested exception is org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.xeno.advertisingsuite.web.domain.PlaylistadMap#6]
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:657)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy54.deletePlayList(Unknown Source)
    at com.xeno.advertisingsuite.web.beans.PlayListBean.deletePlaylist(PlayListBean.java:282)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
    ... 103 more
Caused by: org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.xeno.advertisingsuite.web.domain.PlaylistadMap#6]
    at org.hibernate.impl.SessionImpl.forceFlush(SessionImpl.java:1220)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:188)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669)
    at org.hibernate.engine.CascadingAction.cascade(CascadingAction.java:252)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
    at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
    at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
    at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154)
    at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)

veuillez indiquer comment corriger cette exception.

42
demandé sur Martijn Pieters 2012-07-25 16:03:31

15 réponses

la solution est de faire exactement ce que le message d'exception vous dit:

causé par: org.hiberner.ObjectDeletedException: l'objet supprimé serait sauvegardé de nouveau par cascade ( supprimer l'objet supprimé des associations )

Supprimer l'objet supprimé d'une association (sets, lists, or maps) dans laquelle il se trouve. En particulier, je soupçonne, de PlayList.PlaylistadMaps . Il ne suffit pas de supprimer le objet, vous devez le retirer de toute collection en cascade qui s'y réfère.

en fait, puisque votre collection a orphanRemoval = true , vous n'avez pas besoin de la supprimer explicitement. Vous avez juste besoin de l'enlever du plateau.

40
répondu Tom Anderson 2012-07-25 12:40:45

Problème résolu après avoir changé le FetchType en Lazy

21
répondu Mahmoud Saleh 2012-07-26 10:57:45

si vous ne savez pas, quelle collection détient votre objet

dans mon cas, il était vraiment difficile d'appliquer la solution de TomAnderson, car je ne savais pas ce qu'était la collection, qui contient un lien vers un objet, alors voici la façon de savoir, quels objets contiennent le lien vers l'objet supprimé: dans le débogueur, vous devez entrer le niveau d'exécution le plus bas avant que l'exception ne soit lancée, il devrait y avoir une variable appelée entityEntry , donc vous obtenez un objet PersistenceContext à partir de cette variable: entityEntry.persistenceContext .

pour moi persistenceContext était une instance de StatefulPersistenceContext et cette implémentation a private champ parentsByChild , à partir duquel vous pouvez récupérer des informations sur la collection, qui contient l'élément.

j'utilisais Eclipse debugger, donc il était assez difficile de récupérer ce champ privé d'une manière directe, donc j'ai utilisé Detail Formatter ( Comment puis-je regarder des champs privés d'autres objets directement dans le IDE lors du débogage? )

après avoir obtenu cette information, la solution de TomAnderson peut être appliquée.

4
répondu Dmitry Ginzburg 2017-05-23 11:47:36

j'ai pu résoudre cela en écrivant le code ci-dessous. J'ai utilisé executeUpdate à la place .supprimer ()

def publicSupport = caseObj?.client?.publicSupport
        if(publicSupport)
            PublicSupport.executeUpdate("delete PublicSupport c where c.id = :publicSupportId", [publicSupportId:publicSupport.id])
            //publicSupport.delete()
2
répondu user742102 2013-04-10 07:07:00

j'ai aussi rencontré ce message d'exception. Pour moi, le problème était différent. Je voulais supprimer un parent.

dans une transaction: J'ai appelé le parent de la base de données. Puis j'ai appelé un élément enfant d'une collection dans le parent. Puis j'ai référencé un champ dans l'Enfant (id) Puis j'ai supprimé le parent. Ensuite, j'ai appelé commettre. J'ai eu la "objet supprimé serait réenregistré" erreur.

il s'avère que j'ai dû faire deux séparés transaction. Je me suis engagé après avoir fait référence au domaine de l'enfant. Puis a démarré une nouvelle propagation pour la suppression.

il n'était pas nécessaire de supprimer les éléments enfant ou vider les collections dans le parent (en supposant orphanRemoval = true.). En fait, cela n'a pas fonctionné.

En somme, cette erreur s'affiche si vous avez une référence à un champ dans un objet enfant lorsque l'objet est supprimé.

2
répondu Jake 2015-07-22 00:08:14

C'est une sorte d'Inception qui se passe ici.

for (PlaylistadMap playlistadMap : playlistadMaps) {
        PlayList innerPlayList = playlistadMap.getPlayList();
        for (Iterator<PlaylistadMap> iterator = innerPlayList.getPlaylistadMaps().iterator(); iterator.hasNext();) {
            PlaylistadMap innerPlaylistadMap = iterator.next();
            if (innerPlaylistadMap.equals(PlaylistadMap)) {
                iterator.remove();
                session.delete(innerPlaylistadMap);
            }
        }
    }
1
répondu Ben Tennyson 2015-06-22 18:00:48

un peu comment toutes les solutions ci-dessus n'ont pas fonctionné en hibernation 5.2.10.Final.

mais le réglage de la carte à null comme ci-dessous travaillé pour moi:

playlist.setPlaylistadMaps(null);
1
répondu KayV 2017-11-29 10:19:42

une autre solution

je suis complètement d'accord avec redochka et Nikos Paraskevopoulos . Mahmoud Saleh 's réponse d'obtenir sur la question, dans certaines circonstances, pas tout le temps. Dans ma situation, j'ai vraiment besoin de FetchType impatient. De sorte que Pierreux mentionné ci-dessus Je viens juste de retirer d'une liste qui cantian l'objet aussi. Voici mon code:

Rju entité

public class Rju extends AbstractCompany implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 4294142403795421252L;


    //this field just duplicates @Column(name="callname") and serves for mapping to Rju fullname field
    @Column(name = "fullname")
    private String namerju;
    @NotEmpty
    @Column(name = "briefname")
    private String briefname;

    @LazyCollection(LazyCollectionOption.FALSE)
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "otd")
    private Collection<Vstan> vStanCollection;

//  @LazyCollection(LazyCollectionOption.FALSE)
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "rju", orphanRemoval = true)
    private Collection<Underrju> underRjuCollection;
.........
}

Underrju entité

public class Underrju extends AbstractCompany implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 2026147847398903848L;


    @Column(name = "name")
    private String name;

    @NotNull
    @Valid
    @JoinColumn(name = "id_rju", referencedColumnName = "id")
    @ManyToOne(optional = false)
    private Rju rju;
......getters and setters..........
}

et mon UnderrjuService

@Service("underrjuService")
@Transactional
public class UnderRjuServiceImpl implements UnderRjuService {

    @Autowired
    private UnderRjuDao underrjuDao;

    .............another methods........................
    @Override
    public void deleteUnderrjuById(int id) {
        Underrju underrju=underrjuDao.findById(id);
        Collection<Underrju> underrjulist=underrju.getRju().getUnderRjuCollection();
        if(underrjulist.contains(underrju)) {
            underrjulist.remove(underrju);
        }
        underrjuDao.delete(id);

    }
     .........................
}
1
répondu Frank 2018-06-06 06:15:57

parce que j'ai besoin de FetchType pour être EAGER , je supprime toutes les associations en les définissant à (null) et enregistrer l'objet (qui suppriment toute association dans la base de données) puis supprimer!

qui ajoutent quelques millisecondes mais c'est très bien pour moi, s'il y a un meilleur moyen de garder ces MS ajouter votre commentaire ci-dessous..

Espérer que l'aide à quelqu'un :)

0
répondu Smile2Life 2014-02-06 12:42:40

j'ai également rencontré cette erreur sur une base de données mal conçue, où il y avait une table Person avec une seule relation avec une table Code et une table Organization avec une seule relation avec la même table Code . Le Code pourrait s'appliquer à la fois à une organisation et à une personne, selon la situation. L'objet "personne" et L'Objet "Organisation" ont été définis à Cascade=All delete orphans.

quoi toutefois, ni la personne ni l'organisation ne pouvaient supprimer en cascade parce qu'il y avait toujours une autre collection qui avait une référence à elle. Donc peu importe comment il a été supprimé dans le code Java hors de n'importe quel référencement des collections ou des objets que la suppression aurait échoué. La seule façon de l'obtenir pour fonctionner est de le supprimer de la collection j'ai essayé de l'enregistrer puis de les supprimer de la table de Code directement puis enregistrez la collection. De cette façon il n'y a aucune référence à elle.

0
répondu Uncle Iroh 2015-01-02 22:10:57

ce post contient un truc brillant pour détecter où le problème de cascade est:

Essayez de remplacer sur Cascade à l'époque avec Cascade.None() jusqu'à ce que vous ne recevez pas l'erreur et alors vous avez détecté la cascade causant le problème.

puis résoudre le problème soit par changer la cascade originale à quelque chose d'autre ou en utilisant Tom Anderson réponse.

0
répondu Morten Holmgaard 2017-05-23 11:33:26

j'ai eu la même exception, provoquée en essayant de retirer l'enfant de la personne (Person - OneToMany - Kid). Annotation côté personne:

@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, ... cascade    = CascadeType.ALL)
public Set<Kid> getKids() {    return kids; }

Sur Kid côté annotation:

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "person_id")
public Person getPerson() {        return person;    }

donc la solution était de supprimer cascade = CascadeType.ALL , juste simple: @ManyToOne sur la classe Kid et il a commencé à travailler comme prévu.

0
répondu Oleh Podolyan 2016-10-17 21:10:24

j'avais le même problème. J'essayais de supprimer et d'insérer dans la même transaction. J'ai ajouté theEntityManager.flush(); après theEntityManager.remove(entity); .

0
répondu Jai 2017-06-20 04:55:20

Avait la même erreur. Retirer l'objet du modèle a fait l'affaire.

Code qui montre l'erreur:

void update() {
    VBox vBox = mHboxEventSelection.getVboxSelectionRows();

    Session session = HibernateUtilEventsCreate.getSessionFactory().openSession();
    session.beginTransaction();

    HashMap<String, EventLink> existingEventLinks = new HashMap<>();
    for (EventLink eventLink : mEventProperty.getEventLinks()) {
        existingEventLinks.put(eventLink.getEvent().getName(), eventLink);
    }

    mEventProperty.setName(getName());

    for (Node node : vBox.getChildren()) {

        if (node instanceof HBox) {
            JFXComboBox<EventEntity> comboBoxEvents = (JFXComboBox<EventEntity>) ((HBox) node).getChildren().get(0);
            if (comboBoxEvents.getSelectionModel().getSelectedIndex() == -1) {
                Log.w(TAG, "update: Invalid eventEntity collection");
            }

            EventEntity eventEntity = comboBoxEvents.getSelectionModel().getSelectedItem();
            Log.v(TAG, "update(" + mCostType + "): event-id=" + eventEntity.getId() + " - " + eventEntity.getName());

            String split = ((JFXTextField) (((HBox) node).getChildren().get(1))).getText();
            if (split.isEmpty()) {
                split = "0";
            }
            if (existingEventLinks.containsKey(eventEntity.getName())) {
                // event-link did exist
                EventLink eventLink = existingEventLinks.get(eventEntity.getName());
                eventLink.setSplit(Integer.parseInt(split));
                session.update(eventLink);
                existingEventLinks.remove(eventEntity.getName(), eventLink);
            } else {
                // event-link is a new one, so create!
                EventLink link1 = new EventLink();

                link1.setProperty(mEventProperty);
                link1.setEvent(eventEntity);
                link1.setCreationTime(new Date(System.currentTimeMillis()));
                link1.setSplit(Integer.parseInt(split));

                eventEntity.getEventLinks().add(link1);
                session.saveOrUpdate(eventEntity);
            }

        }
    }

    for (Map.Entry<String, EventLink> entry : existingEventLinks.entrySet()) {
        Log.i(TAG, "update: will delete link=" + entry.getKey());
        EventLink val = entry.getValue();
        mEventProperty.getEventLinks().remove(val); // <- remove from model
        session.delete(val);
    }

    session.saveOrUpdate(mEventProperty);

    session.getTransaction().commit();
    session.close();
}
0
répondu Martin Pfeffer 2017-10-30 12:17:14
cascade = { CascadeType.ALL }, fetch = FetchType.LAZY
-1
répondu chris77 2015-08-22 04:25:27