Hello,
I would sincerely appreciate it if anyone could have a quick look at this and let me know where I'm going wrong.
I can supply complete mapping files, SQL traces etc, but to try and keep things as compact as possible I am going to just put up my test case which at least may give you an idea of where the fault lies. I've included mapping file fragments in the body of the test case.
I am using Hibernate 3.2.2 on MySQL 5.0.27.
It's a reasonably simple model -
A 'Project' has a list of 'ContactList' objects
A 'ContactList' has a list of 'Person' objects
A Person has a single Organisation object
There are things that complicate it a bit:
A 'ContactList' has a back reference to the 'Project'
An 'Organisation' has a back reference to a set of 'Person' objects
Here is my test case:
Code:
public void testAddPersonToExistingStaticList(){
//first, create a bunch of people...
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
p1.setFirstName("Test");
p1.setLastName("Person 1");
p2.setFirstName("Test");
p2.setLastName("Person 2");
p3.setFirstName("Test");
p3.setLastName("Person 3");
//All the people are in the same organisation...
Organisation o1 = new Organisation();
o1.setName("Organisation 1");
p1.setOrganisation(o1);
p2.setOrganisation(o1);
p3.setOrganisation(o1);
/**
* 'Person' HBM Fragment:
* <many-to-one name="organisation" class="Organisation"
* not-null="false" lazy="false" cascade="save-update">
* <column name="orgID" />
* </many-to-one>
*/
//save all people (this works fine)
applicationService.savePerson(p1);
applicationService.savePerson(p2);
applicationService.savePerson(p3);
String testId = String.valueOf(new Date().getTime()); //just a unique id for this test run...
//create a new project (Project is a container for 'ContactLists')
Project project = new Project();
project.setName("Project " + testId);
/**
* 'Project' HBM Fragment:
* <list name="contactLists" cascade="save-update" lazy="false">
* <key column="projectId" not-null="true"/>
* <list-index column="contactListIdx"/>
* <one-to-many class="ContactList"/>
* </list>
*/
//add a list to the project (A contactlist is a collection of people)
ContactListStatic cls = new ContactListStatic();
cls.setListName("Contact List " + testId);
cls.setMyProject(project);
project.getContactLists().add(cls);
/**
* Back reference HBM Fragment:
* <many-to-one name="myProject" lazy="false"
column="projectId"
not-null="true"
insert="false"
update="false"/>
*/
//add a few people to the list
cls.getPeople().add(p1);
cls.getPeople().add(p2);
/**
* 'ContactListStatic' HBM Fragment:
* <subclass name="ContactListStatic" discriminator-value="STATIC">
* <list name="people" lazy="true" cascade="save-update">
* <key column="contactListId" not-null="true"/>
* <index column="personIdx" />
* <many-to-many class="Person" />
* </list>
* </subclass>
*/
//save the new project (this works fine)
applicationService.saveProject(project);
//From an application point of view, this text represents time passing...
//now, we want to add the final person to the (already existing) list...
List cl = applicationService.findContactLists("Contact List " + testId);
ContactListStatic clsRetrieved = (ContactListStatic)cl.get(0);
int numberPeople = applicationService.findNumberInStaticList(clsRetrieved);
assertEquals(numberPeople, 2);
clsRetrieved.getPeople().add(p3);
applicationService.saveProject(clsRetrieved.getMyProject());
//fails, because the organisation o1 is already present in the session...
/*
* org.springframework.orm.hibernate3.HibernateSystemException:
* a different object with the same identifier value was already associated with the session:
* [com.rm.application.model.Organisation#34];
*
* nested exception is org.hibernate.NonUniqueObjectException:
* a different object with the same identifier value was already associated with the session:
* [com.rm.application.model.Organisation#34]
*
* Caused by: org.hibernate.NonUniqueObjectException:
* a different object with the same identifier value was already associated with the session:
* [com.rm.application.model.Organisation#34]
*/
//applicationService.mergeProject(clsRetrieved.getMyProject());
//works, but the newly added person (p3) is missing...
}
There's clearly something silly I'm doing, but I just can't see it.
Will gladly post up any config stuff that will help in sorting this out.
Many thanks.
James.
PS. Full stack trace in case it helps is:
Code:
org.springframework.orm.hibernate3.HibernateSystemException: a different object with the same identifier value was already associated with the session: [com.rm.application.model.Organisation#69]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.rm.application.model.Organisation#69]
Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.rm.application.model.Organisation#69]
at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:577)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$1.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.engine.Cascade.cascade(Cascade.java:97)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:357)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:329)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$1.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
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.engine.Cascade.cascade(Cascade.java:97)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:357)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:329)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$1.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
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.engine.Cascade.cascade(Cascade.java:97)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:357)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:329)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
at org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:684)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:367)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:681)
at com.rm.application.service.io.ApplicationDAOHibernate.saveProject(ApplicationDAOHibernate.java:231)
at com.rm.application.service.ApplicationServiceImpl.saveProject(ApplicationServiceImpl.java:94)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:281)
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 $Proxy1.saveProject(Unknown Source)
at com.rm.application.test.TestApplicationService.testAddPersonToExistingStaticList(TestApplicationService.java:302)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:69)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)