Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleted object would be re-saved by cascade (remove deleted object from associations)

I have the following two entities:

1- PlayList:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "playlist", orphanRemoval = true, cascade =   CascadeType.ALL)
@OrderBy("adOrder")
private Set<PlaylistadMap> PlaylistadMaps = new HashSet<PlaylistadMap>(0);
  • CascadeType.ALL: is needed for save and update on the PlaylistadMap collection when saving or updating the playlist entity.
  • orphanRemoval = true: is needed when deleting the playlist entity, the PlaylistadMap references should be deleteed too.

2- PlaylistadMap:

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

when deleting a playlist by using getCurrentSession().delete(); i am getting the following exception:

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)

please advise how to fix this exception.

like image 598
Mahmoud Saleh Avatar asked Jul 25 '12 12:07

Mahmoud Saleh


3 Answers

The solution is to do exactly what the exception message tells you:

Caused by: org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)

Remove the deleted object from an associations (sets, lists, or maps) that it is in. In particular, i suspect, from PlayList.PlaylistadMaps. It's not enough to just delete the object, you have to remove it from any cascading collections which refer to it.

In fact, since your collection has orphanRemoval = true, you don't need to delete it explicitly. You just need to remove it from the set.

like image 123
Tom Anderson Avatar answered Nov 14 '22 22:11

Tom Anderson


problem solved after changing the FetchType to Lazy

like image 33
Mahmoud Saleh Avatar answered Nov 14 '22 21:11

Mahmoud Saleh


If you don't know, which collection holds your object

In my case it was really hard to apply TomAnderson's solution, since I didn't know what is the collection, which holds a link to an object, so here's the way to know, which objects holds the link to the deleted one: in the debugger you should enter the lowest execution stack level before the exception is thrown, there should be a variable called entityEntry, so you get a PersistenceContext object from this variable: entityEntry.persistenceContext.

For me persistenceContext was an instance of StatefulPersistenceContext and this implementation has private field parentsByChild, from which you can retrieve information about the collection, which contains the element.

I was using Eclipse debugger, so it was kinda hard to retrieve this private field in a straight way, so I used Detail Formatter (How can I watch private fields of other objects directly in the IDE when debugging?)

After getting this information, TomAnderson's solution can be applied.

like image 9
Dmitry Ginzburg Avatar answered Nov 14 '22 22:11

Dmitry Ginzburg