All,
If you've read the previous part of this thread you'll know 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 solution works wonderfully (sessionPerConversation) and I'd like to write it up for the public domain. However, there is the issue of the session cache becoming bloated over time. You can explicitly evict objects when you're done with them of course, 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 do this. I looked into the code and it's surprisingly simple to change - but required 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. 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. 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 [i]WeakReferenceHashMap[/b] that wraps and unwraps the pojos for you (and responds correctly when the weak references get reclaimed) and just change the classes that are created inside PersistantContext. The rest of the code could then remain the same.
Really, this is a very small change and one with huge benefits. You 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!
I haven't implemented this myself yet as I will not be optimising until 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?
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.
|