We are using Hibernate 3.2.6. We have a tree of elements that link to each other in a form like this:
Tree.hbm.exml <many-to-one name="root" column="elementId" cascade="all"/> <!-- points to a first Element --> <set name="allElements" inverse="true" cascade="all-delete-orphan"><key column="ownerTreeId"/><one-to-many class="..."/></set> <!-- Contains all Element objects that belong to this tree --> ...
Element.hbm.xml: <many-to-one name="left" column="elementId" cascade="all"/> <!-- points back to another Element --> <many-to-one name="right" column="elementId" cascade="all"/><!-- points back to another Element --> <many-to-one name="ownerTree" column="ownerTreeId"/> <!-- points back to Root ...
Everything works fine to the point when the tree contains about 300 elements. When the Tree contains more than 300 elements and we attempt to save it, the process fails with a StackOverflowError coming from Hibernate. The stack trace circles around 10 different methods over and over:
at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245) 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.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:431) at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:178) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123) at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:687) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669) at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:245) 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.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:431) at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:178) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123) at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:687) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669) ...
but the top of the stack shows this: at org.hibernate.event.AbstractEvent.<init>(AbstractEvent.java:21) at org.hibernate.event.MergeEvent.<init>(MergeEvent.java:35) at org.hibernate.event.MergeEvent.<init>(MergeEvent.java:20) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:669)
We find it a little odd that only 300 elements in the tree are causing stack overflow. Is there a different way of solving this problem than assigning cascade="all" in the hbm.xml files? Is saving each element of the tree manually and removing cascade="all" from all the hbm.xml files a better solution?
The "allElements" set stores the references to all Element objects that belong to the tree. Is it possible that having multiple references to the same element could be causing the StackOverflowError? Is a set up like this problematic/would you say that we should never have objects with multiple references to the same element?
If an implementation like this is ok and the StackOverflowError is a result of a bug, has such a bug been logged already and possibly addressed in a more recent release of Hibernate?
|