All,
I'm using long-lived sessions (to preserve the first level cache) and demarking transactions at each http request cycle. It's an AJAX webapp, so I'm incrementally changing the data and need this long-lived session cache so that my pojos can use java equality for their references, lazy loaded collections and cascade-loaded sub objects.
The sessionPerConversation solution works wonderfully and I'd like to write up it's application in conjunction with the AJAX framework (ZK) for the public domain. However, there is the issue of the session cache becoming bloated over time. Of course, you can explicitly evict objects when you're done with them, but once you leave the realm of 'one session per fuction' - it's very hard to know when that object is no longer required.
What I would like to do is to utilise the Java Garbage Collection mechanism to evict pojos from session cache. I looked into the hibernate session code and it's a surprisingly simple change - but requires forking the Hibernate source as I can't add this behaviour by extension (as far as I can see).
I've been looking particularly into the source for the Session Cache (the StatefulPersistantContext class) and I'm a little disapointed that it's declared final so that I can't extend it's behavior.
Anyway, Here's my plan...
Inside the stateful cache, pojos are stored in a couple of Map collections, indexed in different ways. This is fine. All I need to do is to change these maps to store WeakReferences to the object instead. For those that didn't know (like myself), WeakReference is an intermediary class that will not be counted as a propper reference by the Garbage Collector when it needs to reclaim some heap memory. This way, as soon as the pojo is not reachable any other way than through the session cache (or any other weak references), the heap can be reclaimed and the pojo can be evicted. Probably the simplest thing would be to implement a WeakReferenceHashMap[/b] that wraps and unwraps the pojos for you (and responds correctly when the weak references get reclaimed) and just use this type of map within PersistantContext. The rest of the code could then remain the same.
Really, this is a [i]very small change with huge benefits and no negatives as far as I can tell. You would no longer need to worry about keeping you session object slim! Sure, if you're loading thousands of pojos at the same time, that'd still be memory intensive - but you'd be free to keep a session arround (as long as the database transaction is returned to the pool) for as long as you like and not worry about any old pojos that have gone out of scope.
Combine this with automatic versioning/refreshing - and it's a perfect solution! For projects like mine I could pretty much ignore the database except to load/save stuff occaisionally.
I haven't implemented this myself yet because I am resisting the temptation to optimise before the end of the project. However, it would only take about half an hour to get working and I'd really rather not fork the hibernate code. Do you think this could be suggeted to the Hibernate team for the next release? Or, at the very least, a way to plugin your own implementation of PersistantContext... How do I go about making this suggestion? Should I write some code and submit it? Does anyone have any comments? Is this a bad idea?
In the mean time - the solution is posted here in principal, so it might proove useful to someone, or to me if I forget about it in three month's time!
Regards,
Ben.
|