Hi,
I read many (if not all) the forum posts regarding lazy loading in thick clients and session strategies / session synchronization. I think I understood why the session is not threadsafe, why synchronizing on the session is usually not considered good practice and why the DB should cope with concurrency etc. Nevertheless, I think I have a case where the "easiest" solution would be to fully synchronize on the session. The problem here is synchronizing the use of the session for lazy loading of collections.
My single-user Swing app uses a tree to view an object graph. Loading the complete graph at once takes much too long (I tried it), so I declare all collections as lazy. When the user expands a node, the tree spawns an extra thread to load the data. My session strategy is best described as "session-per-application-transaction". Basically, I use a new session whenever a new object graph is loaded into the tree. The session stays open, allowing for transparent lazy loading. The user may also edit individual objects from the graph. On clicking [save] I flush and commit the current session from within a thread spawned by our GUI framework when clicking a button.
Problem:
Flush() and commit() happen in a different thread from the lazy loading. Most of the time everything works fine but from time to time I get error messages from Hibernate like the ones shown below. I synchronize all explicit session operations (flush etc.) but I don't know how to synchronize lazy loading on the session object. I read
http://forum.hibernate.org/viewtopic.php?t=925435 and agree with all advice given there, but I think my situation is different.
Is it possible to have lazy initialization synchronize on the session held by the lazy collections? Thanks for any kind of help.
Kay
I use Hibernate 2.1.2.
Here's error message 1:
Code:
10-Mrz-2004 13:52:00 ERROR [Worker 4] | sf.hibernate.AssertionFailure | an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
net.sf.hibernate.AssertionFailure: Hibernate has a bug processing collections
at net.sf.hibernate.impl.SessionImpl$CollectionEntry.postFlush(SessionImpl.java:365)
at net.sf.hibernate.impl.SessionImpl.postFlush(SessionImpl.java:2800)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2205)
at de.continental.fits.hibernate.FitsDatastoreManagedSessions$FlushCommand.perform(FitsDatastoreManagedSessions.java:645)
at de.continental.fits.hibernate.FitsDatastoreManagedSessions.perform(FitsDatastoreManagedSessions.java:540)
at de.continental.fits.hibernate.FitsDatastoreManagedSessions.commit(FitsDatastoreManagedSessions.java:583)
at de.continental.fits.datastore.UnitOfWork.commit(UnitOfWork.java:157)
at de.continental.fits.gui.base.MainModel.commit(MainModel.java:112)
at de.continental.fits.gui.forms.MeasurementEditController.actionSave(MeasurementEditController.java:137)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at de.bea.xui.util.MethodCallReflection.invoke(MethodCallReflection.java:32)
at de.bea.xui.call.parser.XuiAccessMethod.getValue(XuiAccessMethod.java:211)
at de.bea.xui.call.parser.XuiDefaultCall.getValueNoErrorChecking(XuiDefaultCall.java:89)
at de.bea.xui.XuiThreadManager$WorkerThread.run(XuiThreadManager.java:281)
And error message 2:
Code:
java.lang.NullPointerException
at net.sf.hibernate.collection.Set.size(Set.java:107)
at java.util.ArrayList.<init>(ArrayList.java:132)
at de.continental.fits.gui.base.TestPlanTabModel.getTestPlanChildren(TestPlanTabModel.java:270)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at de.bea.xui.util.MethodCallReflection.invoke(MethodCallReflection.java:32)
at de.bea.xui.call.parser.XuiAccessMethod.getValue(XuiAccessMethod.java:211)
at de.bea.xui.call.parser.XuiDefaultCall.getValue(XuiDefaultCall.java:109)
at de.bea.xui.call.parser.XuiDefaultCall.getValue(XuiDefaultCall.java:80)
at de.bea.xui.component.XuiTree$XuiTreeCoreModel.retrieveChildren(XuiTree.java:1044)
at de.bea.xui.component.XuiTree$XuiTreeCoreModel.getChildren(XuiTree.java:957)
at de.bea.xui.component.XuiTree$XuiTreeCoreModel.getIndexOfChild(XuiTree.java:970)
at de.bea.xui.component.XuiTree$XuiTreeCoreModel.getPath(XuiTree.java:1188)
at de.bea.xui.component.XuiTree$XuiTreeCoreModel.getPath(XuiTree.java:1178)
at de.bea.xui.component.XuiTree$XuiTreeRootChanger.work(XuiTree.java:1399)
at de.bea.xui.component.XuiTree$XuiTreeWorker.getValue(XuiTree.java:1264)
at de.bea.xui.component.XuiTree$XuiTreeWorker.getValueNoErrorChecking(XuiTree.java:1278)
at de.bea.xui.XuiThreadManager$WorkerThread.run(XuiThreadManager.java:281)