删除的对象将被级联重新保存(从关联中删除删除的对象)
我有以下两个实体:
1-播放列表:
@OneToMany(fetch = FetchType.EAGER, mappedBy = "playlist", orphanRemoval = true, cascade = CascadeType.ALL) @OrderBy("adOrder") private Set<PlaylistadMap> PlaylistadMaps = new HashSet<PlaylistadMap>(0);
- 在保存或更新播放列表实体时,需要使用CascadeType.ALL保存和更新PlaylistadMap集合。
- orphanRemoval = true :在删除播放列表实体时需要,也应删除PlaylistadMap引用。
2-播放列表地图:
@ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "fk_playlist", referencedColumnName = "pkid", nullable = false) private Playlist playlist;
当通过使用getCurrentSession().delete();
播放列表getCurrentSession().delete();
我收到以下例外:
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)
请告知如何解决这个exception。
解决scheme是完全按照exception消息告诉你的:
引起:org.hibernate.ObjectDeletedException:删除的对象将被级联重新保存( 从关联中删除删除的对象 )
从它所在的关联(集合,列表或映射)中删除已删除的对象。特别是,我怀疑从PlayList.PlaylistadMaps
。 仅删除对象是不够的,您必须从引用它的任何级联集合中删除它。
实际上,因为你的集合有orphanRemoval = true
,所以你不需要明确地删除它。 你只需要从集合中删除它。
在将FetchType更改为Lazy后,问题得以解决
我可以通过编写下面的代码来解决这个问题。 我使用executeUpdate而不是.delete()
def publicSupport = caseObj?.client?.publicSupport if(publicSupport) PublicSupport.executeUpdate("delete PublicSupport c where c.id = :publicSupportId", [publicSupportId:publicSupport.id]) //publicSupport.delete()
我也遇到了这个exception消息。 对我来说,问题是不同的。 我想删除父母。
在一个事务中:首先,我从数据库中调用父项。 然后,我从父级集合中调用一个子元素。 然后我引用了一个字段(id)然后我删除了父项。 然后我调用了commit。 我得到了“删除的对象将被重新保存”的错误。
事实certificate,我必须做两个单独的交易。 我在引用孩子的领域后犯了一个错误。 然后开始新的提交删除。
没有必要删除子元素或清空父级中的集合(假设orphanRemoval = true。)。 事实上,这没有奏效。
总而言之,如果您在删除对象时引用了子对象中的字段,则会出现此错误。
如果你不知道,哪个集合保存你的对象
在我的情况下,应用TomAnderson的解决scheme真的很难,因为我不知道什么是集合,它包含一个对象的链接,所以下面是知道哪些对象链接到被删除的对象的方法:在debugging器应该在引发exception之前input最低的执行堆栈级别,应该有一个名为entityEntry
的variables,因此您可以从这个variables中获得一个PersistenceContext
对象: entityEntry.persistenceContext
。
对于我来说, persistenceContext
是StatefulPersistenceContext
一个实例,这个实现有parentsByChild
private
字段,从中你可以获取关于包含元素的集合的信息。
我正在使用Eclipsedebugging器,所以很难直接检索这个私有字段,所以我使用了Detail Formatter
( 在debugging时我怎样才能在IDE中直接监视其他对象的私有字段? )
得到这些信息后,TomAnderson的解决scheme就可以应用了。
在这里开始的types。
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); } } }
因为我需要FetchType作为EAGER ,我通过将它们设置为(空)并保存对象(删除数据库中的所有关联),然后将其删除,删除所有关联!
这增加了一些毫秒,但对我来说很好,如果有更好的方法来保持这些MS添加您的评论下面..
希望有人帮助:)
我也遇到了一个糟糕的devise数据库上的这个错误,那里有一个Person
表与一个Code
表和一个有相同的Code
表one2many关系的Organization
表关系。 守则可以适用于组织或个人,视情况而定。 Person对象和Organization对象都被设置为Cascade = All delete orphans。
然而,代码表的这种重载使用的结果是,人员和组织都不能级联删除,因为总是有另一个集合引用它。 因此,无论从引用集合或对象的Java代码中如何删除,删除都将失败。 唯一的办法就是把它从我试图保存的集合中删除,然后直接从代码表中删除它,然后保存集合。 这样就没有提到它。
这篇文章包含了一个很好的技巧来检测级联问题:
试着用Cascade.None()
replaceCascade ,直到你没有得到错误,然后检测到导致问题的级联。
然后通过改变原来的级联或者使用Tom Anderson的答案来解决问题。
我也有同样的例外,试图从人(人 – OneToMany – 孩子)删除的孩子。 在人员注释上:
@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, ... cascade = CascadeType.ALL) public Set<Kid> getKids() { return kids; }
在小孩方面注解:
@ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "person_id") public Person getPerson() { return person; }
所以解决scheme是去除cascade = CascadeType.ALL
,只是简单: @ManyToOne
在Kid类,它开始按预期工作。
我有同样的问题。 我试图删除并插入相同的交易。 我添加了theEntityManager.flush();
在theEntityManager.remove(entity);
。
有同样的错误。 从模型中删除对象的伎俩。
显示错误的代码:
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(); }
cascade = { CascadeType.ALL }, fetch = FetchType.LAZY