J’ai les deux entités suivantes:
1- PlayList:
@OneToMany(fetch = FetchType.EAGER, mappedBy = "playlist", orphanRemoval = true, cascade = CascadeType.ALL) @OrderBy("adOrder") private Set PlaylistadMaps = new HashSet(0);
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 à l’aide de getCurrentSession().delete();
Je reçois 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$5.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.
La solution consiste à faire exactement ce que le message d’exception vous indique:
Causé par: org.hibernate.ObjectDeletedException: l’object supprimé serait réenregistré en cascade ( suppression de l’object supprimé des associations )
Supprimez l’object supprimé des associations (ensembles, listes ou mappes) dans lesquelles il se trouve. En particulier, je PlayList.PlaylistadMaps
de PlayList.PlaylistadMaps
. Il ne suffit pas de supprimer l’object, vous devez le supprimer de toutes les collections en cascade qui y font référence.
En fait, puisque votre collection a orphanRemoval = true
, vous n’avez pas besoin de le supprimer explicitement. Vous avez juste besoin de le retirer de l’ensemble.
problème résolu après avoir changé le FetchType en Lazy
Dans mon cas, il était vraiment difficile d’appliquer la solution de TomAnderson, car je ne savais pas quelle est la collection, qui contient un lien vers un object, alors voici la manière de savoir, quels objects contiennent le lien vers l’object supprimé: le débogueur, vous devez entrer le niveau de stack d’exécution le plus bas avant que l’exception soit levée, il doit y avoir une variable appelée entityEntry
, vous obtenez donc un object PersistenceContext
partir de cette variable: entityEntry.persistenceContext
.
Pour moi, persistenceContext
était une instance de StatefulPersistenceContext
et cette implémentation a private
champ private
parentsByChild
, à partir duquel vous pouvez récupérer des informations sur la collection, qui contient l’élément.
J’utilisais le débogueur Eclipse, il était donc difficile de récupérer ce champ privé de manière directe, alors j’ai utilisé Detail Formatter
( Comment puis-je regarder les champs privés d’autres objects directement dans l’EDI lors du débogage? )
Après avoir obtenu ces informations, la solution de TomAnderson peut être appliquée.
J’ai pu résoudre ce problème en écrivant le code ci-dessous. J’ai utilisé executeUpdate au lieu de .delete ()
def publicSupport = caseObj?.client?.publicSupport if(publicSupport) PublicSupport.executeUpdate("delete PublicSupport c where c.id = :publicSupportId", [publicSupportId:publicSupport.id]) //publicSupport.delete()
J’ai également rencontré ce message d’exception. Pour moi, le problème était différent. Je voulais supprimer un parent.
En une seule transaction: j’ai d’abord appelé le parent depuis la firebase database. Ensuite, j’ai appelé un élément enfant d’une collection dans le parent. Ensuite, j’ai référencé un champ dans l’enfant (id) Puis j’ai supprimé le parent. Ensuite, j’ai appelé commit. J’ai eu l’erreur “l’object supprimé serait réenregistré”.
Il s’avère que je devais effectuer deux transactions distinctes. Je me suis engagé après avoir référencé le champ chez l’enfant. Ensuite, a lancé un nouveau commit pour la suppression.
Il n’était pas nécessaire de supprimer les éléments enfants ou de vider les collections dans le parent (en supposant que orphanRemoval = true.). En fait, cela n’a pas fonctionné.
En résumé, cette erreur apparaît si vous avez une référence à un champ dans un object enfant lorsque cet object est en cours de suppression.
Genre de création en cours ici.
for (PlaylistadMap playlistadMap : playlistadMaps) { PlayList innerPlayList = playlistadMap.getPlayList(); for (Iterator iterator = innerPlayList.getPlaylistadMaps().iterator(); iterator.hasNext();) { PlaylistadMap innerPlaylistadMap = iterator.next(); if (innerPlaylistadMap.equals(PlaylistadMap)) { iterator.remove(); session.delete(innerPlaylistadMap); } } }
Certains comment toutes les solutions ci-dessus n’ont pas fonctionné dans Hibernate 5.2.10.Final.
Mais mettre la carte à null comme ci-dessous a fonctionné pour moi:
playlist.setPlaylistadMaps(null);
Je suis complètement d’accord avec Redochka et Nikos Paraskevopoulos . La réponse de Mahmoud Saleh résout le problème dans certaines circonstances, pas à chaque fois. Dans ma situation, j’ai vraiment besoin du type de récupération Eager. Donc, comme Stony mentionné ci-dessus, je viens de retirer d’une liste qui cantian l’object aussi. Voici mon code:
Entité Rju
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 Ssortingng namerju; @NotEmpty @Column(name = "briefname") private Ssortingng briefname; @LazyCollection(LazyCollectionOption.FALSE) @OneToMany(cascade = CascadeType.ALL, mappedBy = "otd") private Collection vStanCollection; // @LazyCollection(LazyCollectionOption.FALSE) @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "rju", orphanRemoval = true) private Collection underRjuCollection; ......... }
Entité Underrju
public class Underrju extends AbstractCompany implements Serializable { /** * */ private static final long serialVersionUID = 2026147847398903848L; @Column(name = "name") private Ssortingng 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 underrjulist=underrju.getRju().getUnderRjuCollection(); if(underrjulist.contains(underrju)) { underrjulist.remove(underrju); } underrjuDao.delete(id); } ......................... }
Parce que j’ai besoin de FetchType pour être EAGER , je supprime toutes les associations en les définissant sur (null) et enregistre l’object (qui supprime toute association dans la firebase database) puis le supprime!
Cela ajoute quelques millisecondes, mais ça me va, s’il y a un meilleur moyen de garder ces MS append votre commentaire ci-dessous ..
J’espère que ça aide quelqu’un 🙂
J’ai également rencontré cette erreur sur une firebase database mal conçue, où il y avait une table Person
avec une relation one2many avec une table Code
et une table Organization
avec une relation one2many avec la même table Code
. Le code pourrait s’appliquer à la fois à une organisation et à une personne, selon la situation. L’object Person et l’object Organisation ont tous deux été définis sur Cascade = All delete orphans.
Ce qui est devenu de cette utilisation surchargée de la table de code, cependant, c’est que ni la personne ni l’Organisation ne pouvaient supprimer en cascade, car il y avait toujours une autre collection qui y faisait référence. Ainsi, peu importe comment il a été supprimé dans le code Java à partir des collections ou des objects référençant, la suppression échoue. La seule façon de le faire fonctionner était de le supprimer de la collection que j’essayais d’enregistrer, puis de le supprimer directement de la table de code, puis de sauvegarder la collection. De cette façon, il n’y avait aucune référence à cela.
Cet article contient un truc génial pour détecter où se trouve le problème en cascade:
Essayez de remplacer Cascade à la fois par Cascade.None()
jusqu’à ce que vous Cascade.None()
pas l’erreur et que vous ayez détecté la cascade à l’origine du problème.
Ensuite, résolvez le problème en changeant la cascade originale en une autre chose ou en utilisant la réponse de Tom Anderson .
J’ai eu la même exception, lors de la tentative d’enlever l’enfant de la personne (Personne – OneToMany – Kid). Sur l’annotation côté personne:
@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, ... cascade = CascadeType.ALL) public Set getKids() { return kids; }
Sur l’annotation côté enfant:
@ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "person_id") public Person getPerson() { return person; }
La solution était donc de supprimer cascade = CascadeType.ALL
, simplement simple: @ManyToOne
sur la classe Kid et il a commencé à fonctionner comme prévu.
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);
.
Eu la même erreur. Supprimer l’object 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 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 comboBoxEvents = (JFXComboBox ) ((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()); Ssortingng 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 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(); }
cascade = { CascadeType.ALL }, fetch = FetchType.LAZY