Greetings,
I'm trying to test orphan deletion in my unit tests. Maybe the problem is not in Hibernate but in Spring AbstractJpaTests which I'm subclassing, but still I'd like to describe my "error path"
I have an entity Oem, which has collection of Make objects, mapped with
Code:
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, mappedBy="oem")
@org.hibernate.annotations.Cascade(
value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN
)
In my test, I do the following:
Code:
public void testDeleteMake() throws Exception
{
Oem oem = // setup oem
oemDao.updateOem(oem); // -- this should remove a Make "GM_MAKE2" from Oem's collection.
assertNull(getCommonService().getMake("GM_MAKE2")); //-- [b]THROWS AN EXCEPTION SHOWN BELOW!!![/b]
}
which is throwing the error:
Code:
Caused an ERROR
Removing a detached instance com.trilogy.orderagent.datamodel.Make#1002; nested exception is java.lang.IllegalArgumentException: Removing a detached instance com.trilogy.orderagent.datamodel.Make#1002
org.springframework.dao.InvalidDataAccessApiUsageException: Removing a detached instance com.trilogy.orderagent.datamodel.Make#1002; nested exception is java.lang.IllegalArgumentException: Removing a detached instance com.trilogy.orderagent.datamodel.Make#1002
Caused by: java.lang.IllegalArgumentException: Removing a detached instance com.trilogy.orderagent.datamodel.Make#1002
at org.hibernate.ejb.event.EJB3DeleteEventListener.performDetachedEntityDeletionCheck(EJB3DeleteEventListener.java:47)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:86)
at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:775)
at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:758)
at org.hibernate.engine.Cascade.deleteOrphans(Cascade.java:355)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:324)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:131)
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:122)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:65)
at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:35)
at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:969)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1114)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:64)
at org.springframework.orm.jpa.JpaTemplate$9.doInJpa(JpaTemplate.java:305)
at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:183)
at org.springframework.orm.jpa.JpaTemplate.executeFind(JpaTemplate.java:150)
at org.springframework.orm.jpa.JpaTemplate.find(JpaTemplate.java:297)
at com.trilogy.common.CommonServiceImpl.getMake(CommonServiceImpl.java:247)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:280)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:187)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:154)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:210)
at $Proxy21.getMake(Unknown Source)
at com.trilogy.dm.DealerMaintenanceServiceTest.testDeleteMake(DealerMaintenanceServiceTest.java:144)
at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:69)
at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.access$001(AbstractAnnotationAwareTransactionalTests.java:44)
at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests$1.run(AbstractAnnotationAwareTransactionalTests.java:112)
at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTest(AbstractAnnotationAwareTransactionalTests.java:177)
at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runTestTimed(AbstractAnnotationAwareTransactionalTests.java:150)
at org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests.runBare(AbstractAnnotationAwareTransactionalTests.java:108)
at org.springframework.test.jpa.AbstractJpaTests.runBare(AbstractJpaTests.java:159)
at org.springframework.test.jpa.AbstractJpaTests.runBare(AbstractJpaTests.java:239)
As far as I can see, my attempt to access a Make after calling a business method triggers orphan deletion, but it fails due to incorrect object state.
Do you have any pointers, guys? Is this a Hibernate glitch or "user error"? ;)