I'm really happy with the recent changes I've done to make Hibernate more
extensible and more understandable. *Finally* the SessionImpl class is
starting to get smaller instead of bigger... The main points of redesign:
* pulled all querying and loading functionality out of SessionImpl into the
Loader heirarchy
* abstracted ClassPersister to allow pluggable persistence mechanisms
* replaced the "deferred loading" feature with a new "2-phase load"
* simplified versioning (which had actually been broken)
The third point (which I implemented last night) is to do with processing an
SQL ResultSet when objects contained earlier in the ResultSet might have
associations to objects later in the ResultSet. Hibernate used to deal with
this using a variant of the flyweight pattern where it would instantiate the
associated object but not actually try to initialize it till after the
ResultSet was fully processed. If it happened to find the object later in
the ResultSet, it would initialize it then.
The disadvantages of this approach were:
1. It couldn't work for polymorphic classes (we need to know the exact
subclass of the associated object to instantiate it)
2. It turned out to be horrendously complicated and bug-inducing
The new approach is to load objects in two phases
phase 1: (while processing the ResultSet) instantiate objects and grab their
state into an array, representing associations with an identifier
phase 2: (after the ResultSet is finished) resolve identifiers into the
associated objects and then initialize the object
This has one extra advantage in addition to 1 + 2 no longer applying
3. We don't need to use concurrent open ResultSets
It turns out that this approach is *much* simpler and better and I'm
embarrassed for not realizing that fact earlier (I knew that it existed as
an alternative!) I got rid of some of the most difficult code in SessionImpl
and removed about 3 instance variables.
P.S. I am already working on multi-table persistence for those who need
it....
|