Okay - so even if I take Spring out of the picture:
Code:
org.hibernate.PropertyAccessException: Exception occurred inside setter of org.thorne.lettings.referencedata.api.AddressImpl.area
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:51)
at org.hibernate.tuple.AbstractTuplizer.setPropertyValues(AbstractTuplizer.java:207)
at org.hibernate.tuple.PojoTuplizer.setPropertyValues(PojoTuplizer.java:176)
at org.hibernate.persister.entity.BasicEntityPersister.setPropertyValues(BasicEntityPersister.java:2919)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:113)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:530)
at org.hibernate.loader.Loader.doQuery(Loader.java:436)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)
at org.hibernate.loader.Loader.loadCollection(Loader.java:1434)
at org.hibernate.loader.collection.OneToManyLoader.initialize(OneToManyLoader.java:111)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:488)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1430)
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:280)
at org.hibernate.engine.PersistenceContext.initializeNonLazyCollections(PersistenceContext.java:796)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:223)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1345)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:116)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:101)
at org.hibernate.persister.entity.BasicEntityPersister.load(BasicEntityPersister.java:2471)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:351)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:332)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:113)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:167)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:79)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:621)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:614)
at ContactAssociationTest.testStackOverflow4(ContactAssociationTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:78)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:40)
... 50 more
Caused by: org.hibernate.LazyInitializationException: illegal access to loading collection
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:172)
at org.hibernate.collection.AbstractPersistentCollection.write(AbstractPersistentCollection.java:61)
at org.hibernate.collection.PersistentSet.add(PersistentSet.java:158)
at org.thorne.lettings.referencedata.api.AreaImpl.addAddress(AreaImpl.java:45)
at org.thorne.lettings.referencedata.api.AddressImpl.setArea(AddressImpl.java:100)
... 55 more
it's basically exactly the same exception.
And now I've upgraded to Hibernate3.
Now without me resorting to posting a lot of code a simple explanation of this is that I'm simply doing a session.get() for a known parent object, which participates in a one-to-many parent child relationship.
I've coded up some simple methods on the parent which go like:
public void addChild(Child c){
this.collection.add(c);
c.setParent(this);
}
and here's the important bit, where I think the problem lies: I've also coded some simple methods on the child which go like:
public void setParent(Parent p){
this.parent = p;
p.addChild(this);
}
this is what I've not seen before in the examples - where a change in the child's parent means the child tries to add itself as a child to that parent.
Now I've got some other bits in there to stop a recursive loop, but from the stack trace I can see this:
Code:
Caused by: org.hibernate.LazyInitializationException: illegal access to loading collection
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:172)
at org.hibernate.collection.AbstractPersistentCollection.write(AbstractPersistentCollection.java:61)
at org.hibernate.collection.PersistentSet.add(PersistentSet.java:158)
at org.thorne.lettings.referencedata.api.AreaImpl.addAddress(AreaImpl.java:45)
at org.thorne.lettings.referencedata.api.AddressImpl.setArea(AddressImpl.java:100)
so Area is the parent and Address is the child.
It looks to me that when I ask the session to get the parent, it is setting up the relationships with setArea calls on the Addresses. That in turn results in a call to addAddress on the Area as outlined in the parent/child snippet above.
This causes an access of the underlying collection on the parent which throws the exception.
Now, am I wrong to try and manage parent relationships from a child? And is this what the problem is? As I've mentioned before, I can temporarily disable this by adding a Hibernate.isInitialized(area.getAddresses()) to the child's setArea method but this is a bad dependency for me.