I think this is an one-to-many with proxied object setting problem ...
The scenario : Item and Series have bi-directional many-to-one relation , that is :
one Item may belong to ZERO (not-found="ignore") or ONE Series ,
one Series may contain ZERO or MANY Items.
In Item.java , I have one method : setSeries(Series s)
Code:
public void setSeries(Series s)
{
if (getSeries() != null)
getSeries().getItems().remove(this);
series = s;
if (s != null)
s.getItems().add(this);
}
In Series.java , I have one method : addItem(Item item)
Code:
public void addItem(Item item)
{
if (item == null)
throw new IllegalArgumentException("Null item");
items.add(item);
item.setSeries(this);
}
When I create one Series with more (or equal to) 2 items , it will throw ConcurrentModificationException
(Creating series with one item will be OK)
The code is below:
Code:
Series series1 = new Series();
series1.setName("series1");
Item item1 = new Item();
item1.setNumber("item1");
Item item2 = new Item();
item2.setNumber("item2");
series1.addItem(item1);
series1.addItem(item2);
seriesDao.create(series1); <-- This is where the exception was thrown
SeriesDao is just a class extends HibernateDaoSupport (from Spring) and implements AbstractDao<T> (just CRUD actions)
Code:
public abstract class AbstractHibernateDao<T> extends HibernateDaoSupport implements AbstractDao<T>
{
...
public Serializable create(T po)
{
return getHibernateTemplate().save(po);
}
...
}
It seems the problem occurs because of iterating the relationsip of proxied_Series and proxied_Items.
I know it can be solved with access="field" in <many-to-one name="series" ...> (and I really solved it with this)
But I think access="field" is a little ... 'dirty' ....
Is there any way to get out of the Exception without access="field" ???
Thank you very much.
Hibernate version:3.0.5 Mapping documents:Item :
Code:
<class name="Item">
<many-to-one name="series" column="SeriesID" class="Series" lazy="true" cascade="save-update" not-found="ignore"/>
</class>
Series :
Code:
<class name="Series">
<set name="items" lazy="true" inverse="true" cascade="save-update">
<key column="SeriesID"/>
<one-to-many class="Item"/>
</set>
</class>
Full stack trace of any exception that occurs:Code:
ERROR - onTearDown error
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$KeyIterator.next(Unknown Source)
at org.hibernate.collection.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:366)
at org.hibernate.engine.Cascades.cascadeCollection(Cascades.java:895)
at org.hibernate.engine.Cascades.cascadeAssociation(Cascades.java:792)
at org.hibernate.engine.Cascades.cascade(Cascades.java:720)
at org.hibernate.engine.Cascades.cascade(Cascades.java:847)
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:121)
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:112)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:59)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:490)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:495)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:468)
at org.springframework.test.AbstractTransactionalSpringContextTests.endTransaction(AbstractTransactionalSpringContextTests.java:206)
at org.springframework.test.AbstractTransactionalSpringContextTests.onTearDown(AbstractTransactionalSpringContextTests.java:152)
at org.springframework.test.AbstractDependencyInjectionSpringContextTests.tearDown(AbstractDependencyInjectionSpringContextTests.java:253)
at junit.framework.TestCase.runBare(TestCase.java:130)
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.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Name and version of the database you are using:MySQL 3.23.58