我有以下两个实体:
1- PlayList:
@OneToMany(fetch = FetchType.EAGER, mappedBy = "playlist", orphanRemoval = true, cascade = CascadeType.ALL)
@OrderBy("adOrder")
private Set<PlaylistadMap> PlaylistadMaps = new HashSet<PlaylistadMap>(0);
2- PlaylistadMap:
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "fk_playlist", referencedColumnName = "pkid", nullable = false)
private Playlist playlist;
使用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)
请告知如何修复此异常。
答案 0 :(得分:41)
解决方案是完全按照异常消息告诉您的内容:
引起:org.hibernate.ObjectDeletedException:已删除的对象将通过级联重新保存(从关联中删除已删除的对象)
从它所在的关联(集合,列表或地图)中删除已删除的对象。特别是,我怀疑,来自PlayList.PlaylistadMaps
。仅仅删除对象是不够的,你必须将它从任何引用它的级联集合中删除。
事实上,由于您的收藏集有orphanRemoval = true
,因此您无需明确删除它。您只需将其从集合中删除即可。
答案 1 :(得分:21)
问题解决了
答案 2 :(得分:5)
在我的情况下,很难应用TomAnderson的解决方案,因为我不知道什么是集合,它拥有一个对象的链接,所以这里有了解的方法,哪些对象包含已删除的链接的链接:在调试器中,您应该在抛出异常之前输入最低执行堆栈级别,应该有一个名为entityEntry
的变量,因此您将得到一个PersistenceContext
对象来自此变量:entityEntry.persistenceContext
。
对我而言persistenceContext
是StatefulPersistenceContext
的一个实例,此实现具有private
字段parentsByChild
,您可以从中检索有关该元素的集合的信息。
我使用的是Eclipse调试器,所以很难直接检索这个私有字段,因此我使用Detail Formatter
(How can I watch private fields of other objects directly in the IDE when debugging?)
获得此信息后,可以应用TomAnderson的解决方案。
答案 3 :(得分:2)
我也遇到过这条例外消息。 对我来说,问题是不同的。 我想删除父母。
在一次交易中:
事实证明我必须做两个单独的交易。 我在引用孩子的字段后提交了。然后开始一个新的删除提交。
无需删除子元素或清空父元素(假设orphanRemoval = true
。)。事实上,这没有用。
总而言之,如果您在删除该对象时引用了子对象中的字段,则会出现此错误。
答案 4 :(得分:2)
我能够通过编写下面的代码来解决这个问题。我使用了executeUpdate而不是.delete()
def publicSupport = caseObj?.client?.publicSupport
if(publicSupport)
PublicSupport.executeUpdate("delete PublicSupport c where c.id = :publicSupportId", [publicSupportId:publicSupport.id])
//publicSupport.delete()
答案 5 :(得分:1)
此类活动正在进行中。
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);
}
}
}
答案 6 :(得分:1)
我完全同意redochka和Nikos Paraskevopoulos。 Mahmoud Saleh的回答在某些情况下不是每次都能解决问题。在我的情况下,我真的需要Eager fetchtype。正如上面提到的Stony 我刚从列表中删除了cantian对象。这是我的代码:
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 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实体
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..........
}
和我的 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);
}
.........................
}
答案 7 :(得分:0)
因为我需要 FetchType 为 EAGER ,我通过将它们设置为(null)来删除所有关联并保存对象(删除数据库中的所有关联)然后删除它!
这增加了几毫秒,但对我来说没问题,如果有更好的方法来保持那些MS添加您的评论...
希望能帮助某人:)
答案 8 :(得分:0)
我还在一个设计糟糕的数据库上遇到了这个错误,其中有一个Person
表与一个Code
表有一个关系,一个Organization
表与一个关系有一个关系相同的Code
表。 “守则”可以根据情况适用于组织和/或人员。 Person对象和Organization对象都设置为Cascade = All delete orphans。
然而,对Code表的这种超载使用的变化是,Person和Organization都不能级联删除,因为总有另一个集合引用它。因此,无论在Java代码中如何删除任何引用集合或对象,删除都将失败。让它工作的唯一方法是从我试图保存的集合中删除它然后直接从Code表中删除它然后保存集合。那样就没有提到它了。
答案 9 :(得分:0)
This post contains a brilliant trick to detect where the cascade problem is:
尝试使用Cascade.None()
替换 Cascade ,直到您没有收到错误,然后您检测到导致问题的级联。
然后通过将原始级联改为其他或使用 Tom Anderson 回答来解决问题。
答案 10 :(得分:0)
我有同样的例外,当试图将这个孩子从这个人身上移除时(Person - OneToMany - Kid)。 在人员方面注释:
@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, ... cascade = CascadeType.ALL)
public Set<Kid> getKids() { return kids; }
关于Kid侧注释:
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "person_id")
public Person getPerson() { return person; }
所以解决办法是删除cascade = CascadeType.ALL
,简单地说:Kid类上的@ManyToOne
,它开始按预期工作。
答案 11 :(得分:0)
我遇到了同样的问题。我试图删除并插入同一个事务中。我在theEntityManager.flush();
之后添加了theEntityManager.remove(entity);
。
答案 12 :(得分:0)
有同样的错误。从模型中删除对象就可以了。
显示错误的代码:
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();
}
答案 13 :(得分:0)
如果您使用PlaylistadMap模式而不是PlayList进行删除,则会发生此问题。 在这种情况下,FetchType = Lazy不是正确的选择。它不会引发任何异常,只会删除PlaylistadMap中的数据,而PlayList中的数据将保留在表中。 还要检查。
答案 14 :(得分:0)
我只是解决这个问题。
答案 15 :(得分:0)
您需要删除映射对象上的关联:
playList.getPlaylistadMaps().setPlayList(null);
session.delete(playList);
答案 16 :(得分:0)
解决方法是“破坏”对象之间的关系,然后再次尝试删除。 答案在您的日志中:
(remove deleted object from associations): [com.xeno.advertisingsuite.web.domain.PlaylistadMap#6]
解释:什么?(删除关联)在哪里?[带有 id#6 的 PlaylistadMap 对象]
答案 17 :(得分:-1)
cascade = { CascadeType.ALL }, fetch = FetchType.LAZY