Tuesday, October 05, 2010

Why Hibernate Session Management needs careful analysis and implementation

What is the most complicated part in Hibernate? I would think it is the session handling. It is quite a confusing topic with a lot of material everywhere, but a lot of them confusing at the best.

I have been Stuggling with the session management for a little time now, with some hibernate errors thrown in every now and then like the ones below

 - Illegal attempt to associate a collection with two open sessions
 - a different object with the same identifier value was already associated with the session
 - LazyInitializationException: could not initialize proxy - no Session Data Access.
 - Many more -----

PHEW !!!.

I decided to take a lot more in-depth view of session handling and after reading some of the articles and books by Gavin King, finally arrived at some conclusions. Then I wrote test implementations for all the patterns and analyzed their behavior. So far the experiments has given me a good stable implementation of session handling so wanted to write a few words about what I found during the my experiments with hibernate.

The EntityManager/Persistence Context (Read Session in Hibernate)

The JPA entity manager is nothing but the session in pure Hibernate terms. I am not going to make an attempt to explain what the session does, but the following features are atmost important.

- Session is the Level 1 cache of Hibernate
- It is a cache of managed entity instances
- It defines the scope of a POJO's persistent Identity

Why Session management is so critical ?

Hibernate believes in Lazy loading (and rightly so). It is the default behavior of the O/R mapper and it tries to defer the loading of a associated Object/Collection till the last moment it could afford. This has the following implications

- If you have many-to-one or many-to-many relationships defined, hibernate will to proxy all of them when the base object is fetched. This means that all the associated objects are not populated by default (Unless you force it to be loaded by a lazy="false" on your XML definition) . It holds only a reference to the IDs of the associated objects making the collection (There are some exceptions to this as to what API was called to get the entity in to persistent state Please see documentation of get() and load() methods)

- The session has to be alive for Hibernate to intialize any of the associated objects it proxied during the initial fetch. Which means that you would get a "LazyInitializationException" if the session is closed and then you call "Entity.getAssociatedCollection()"

Patterns in session management and their applications

session-per-operation:

This is the simplest one of all to understand - In this pattern the session spans only a single operation from the database. The sample code will look like the following

Session sess = factory.openSession();
Transaction tx;
try {
     tx = sess.beginTransaction();
    
     //do a single DB operation
     ...
     tx.commit();
}
catch (Exception e) {
     if (tx!=null)
    tx.rollback();
     throw e;
}
finally {
     sess.close();
}


Though very simple in its implementation, this approach suffers from some serious drawbacks. It absolutely does not use any of Hibernate's lazy loading or L1 cache capabilities. It will force you to agressively load almost all the associated objects on the tree. Mostly this is an anti-pattern and should be avoided as far as possible.

session-per-request:

This is an extension of the session-per-operation pattern, In this pattern the session spans multiple related operations from the database. This approach works prertty good for Client Server applications. the session is closed immediately after the db operation is completed. A sample of this code is shown below.

Session sess = factory.openSession(); 
Transaction tx;
try {
     tx = sess.beginTransaction();
     
     //do multiple related DB operations, Debit account A, Credit Account B etc.
        
     ...
     tx.commit();
}
catch (Exception e) {
     if (tx!=null) 
    tx.rollback();
     throw e;
}
finally {
     sess.close();
}

This pattern though betters the Session-per-operation, is still sub optimal for Web applications where a interaction with the user can span multiple db operations and round trips between Client and Server. The same logic is extended in the "session-per-request-with-detached-objects" pattern to derive some more use of the objects loaded.

session-per-request-with-detached-objects:

Session per request with detached objects extends the above pattern with the promise of "re attaching" the entity back on to a new session when the user has completed modifications on the same. This is a really powerful feature of Hibernate. This really means that you could use your domain POJOs as carriers of information to other layers of the application in a "detached" form. Hibernate makes sure that there is no DB connection maintained durng the think time and also makes sure that the object is re attached to the new session when it is sent back. Amazing and nice for a web app !

Now lets examine this in a little more detail:

As in the session-per-request pattern, the session-per-request-with-detached-objects pattern also uses the session for the duration of multiple related db operations. This pattern relies on implementing a partly "custom aggressive fetch" strategy. As the session gets closed at the end of the DB operations, the code following cannot be relying on the session to initialize the proxied data on the Entity. This means that the designer has to carefully decide what is the granularity of the fetch needed for the "conversation" which is currently taking place.

There are multiple ways to control the depth of the fetch tree. One option is to make the lazy="false" setting on the "entity.hbm.xml" file for the required associations. But this is not a great option unless you are absolutely sure that this entity needs to be always fetched with the associations. A designer has to be extremely careful about setting this option as the associated tree could grow exponentially and could strangle your machine to death.

The better way I have seen is to programatically control the depth of the fetch by using the "initialize" method of the Hibernate Class. In this approach, the code fetching the Entity looks like the following

Transaction tx = null;
long entityIdentifier = 1234;
try
{
    Session hiberSession = HibernateUtil.currentSession();        
    tx = hiberSession.beginTransaction();

    Entity entity = (Entity) hiberSession.get(Entity.class, entityIdentifier);
            
    // initialize the mandatory collections 
            
    Hibernate.initialize(entity.getAttributeValueSet()); //Attribute value many-to many mapping - associated collection
    Hibernate.initialize(entity.getCategories()); //Product categories for this entity - associated collection
                    
            
    return entity;
}
catch (Exception e) 
{
    tx.rollback();
    return null; // OR throw this Error ----- 
}
finally
{
    HibernateUtil.closeSession();
} 

Re attaching the "Detached" Objects:

Once the session is closed after the fetch, the persistent object enters a "detached" state. A "detached" object can be made persistent again by re attaching it to a session. The easiest approach to be followed is to call the "Session.update(Entity)". Hibernate would take care of attaching the object to the current session and make it persistent again. Another option is to use the Session.merge(Entity). You have to be aware that there are some fundamental differences between the "update" and the "merge" which is explained in this document:

Key observations about the pattern:

 - It enables you to use the domain objects as transport objects as they can be detached from their persistent state
 - It forces you to fetch some of the data eagerly as the session is closed before they are accessed
 - Fine grained control of the depth of fetch is possible using programmatic constructs
 - This is suited for applications which use a lot of AJAX calls due to some reasons I have explained in the section below.

session-per-conversation:

The session per conversation pattern leverages the "extension" of the life of a session to the length of a "conversation". In a N-tier web application, the "conversation" can be often longer than the normal single DB operation. There could be considerable think time between the user actions, and the session is kept alive till such time that one complete conversation is completed.

The key advantage of this pattern is that it makes the best use of "lazy loading". The loading of all associations are delayed till such time that it becomes absolutely necessary to load them. This ideally should do away with a lot of the performance overheads with the "eager" loading of associations. The typical way of closing the session in this approach is to write a Servlet Filter where the session is closed just before the view is refreshed. A sample of such a Filter is given below. This filter can be plugged into only those pages which need to close the session when the view is rendered

public class SessionFilter implements Filter
{
    private FilterConfig filterConfig;
    private static Set<String> publicUrls = new HashSet<String>();
    
    //initializer block.
    static 
    {
         //Add urls which demarcate the boundaries of your conversation
         //publicUrls.add("CreateOffer.action");
         
    }    

    @Override
    public void destroy() 
    {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException 
    {
        try {
            chain.doFilter (request, response);
        }
        catch(Exception e) {
            // handle!
        }
        finally {
            HibernateUtil.closeSession();
        }
        
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException 
    {
        // TODO Auto-generated method stub
        
    }
    
    protected boolean isPublicResource(HttpServletRequest request) 
    {
        String resource = request.getServletPath();
        return publicUrls.contains(request.getServletPath());
                
    }
}


One of the key challenges for the designer using this pattern is to clearly identify all "conversation" boundaries. Another problem is that with Web 2.0 and the number of AJAX based applications, the boundaries of the conversation are often blurred. Or rather, sometimes, it is really difficult to identify the boundaries and sometimes it is very easy to do a wrong assessment of the boundary. The pitfall of not able to identify the boundary correctly and failing to insert the filter, can cause some really confusing Errors which are tougher to debug. Sometimes it's easier to go with the detached-objects design in applications with heavy AJAX based transactions.

36 comments:

Anonymous said...

some good information,thanks for sharing

Anonymous said...

So many blogs with so much of information exists out side and its confusing and some times wrong.

you have given a very nice explanation. Thanks for sharing. please add more blogs. It helps learners like me.

Anonymous said...

Actually when someone doesn't understand after that its up to other visitors that they will help, so here it takes place.

Have a look at my homepage ... xerox phaser 8560 printer

Anonymous said...

Sir, pls send out that video clip to my email
I.D. It will certainly be aid ful 2 make pcb easy. Thankyou.


my page :: Xerox Phaser 8560 Driver

Anonymous said...

An exceptional share! I have just forwarded this onto
a coworker who has been conducting a little bit homework on this.
And hubby actually ordered me dinner because
of the fact i always discovered it for him... lol. So i want to
reword this.... Basically meal!! But yeah, thanx
for spending enough time to speak about
this matter here on your blog.

my blog ... www.modellbau-ravina.at

Anonymous said...

How can I download a complimentary version of hplaserjet 1020?


Also visit my website ... easyriderka.wordpress.com

Anonymous said...

My husband and that i continued a snorkeling adventure from the
Keys of Florida. I was told the jellyfish were rampant in the region however it was
safe to search just prevent them, of course , if they sting
it will be unconfortable and not painful. I knew growing up a swimming pool and i also must have been a confident swimmer.
There we were told never to leave our partners and always be around in arms length.
That is just good snorkel safety. Call at the open ocean 30 feet
away from the boat, We are mesmorized because of the reef, My husband and I are bopping around indicating fish together.
Very romantic! Then all the sudden I receive water
during my snorkel, and my instinct will be to grab at something to have my barings.
Only nothing at all is to grab, I will be in the open ocean!

We're 30 feet from the boat! We're coughing i research and then determine
pink circle Jellyfish to the left and right!
I panic gross out and explode for your boat leaving my better half behind.
I could feel him grabbing my foot looking to drag me to the side, in what he later told
me was his try and save me from the jellyfish school I'd been swimming towords, nevertheless it was in its final stages.... I could truthfully feel what seemed like little beestings all up my arm and leg! Epic fail from the romance department!

My site: Handcrafted Jewellery

Anonymous said...

Fantastic beat ! I would like to apprentice at the same time as you amend your site, how could i subscribe for a
weblog site? The account aided me a appropriate deal.
I were tiny bit familiar of this your broadcast offered shiny clear idea

Also visit my blog post - pilgrim jewellery uk online

Anonymous said...

i enjoy the roasted beans necklace and also the tom jeans earrings.
thanks a great deal of!

Here is my webpage ... wiki.brandalive.be

Anonymous said...

Extremely informative post. The price color and multifunction shade laser printers must have been taken
care of. They're still more costly compared to inkjet printers although worth the added prices.

my web blog xerox phaser 8560 color printer

Anonymous said...

exactly how can i do this on a mac.

Here is my webpage: xerox phaser 8560 driver

Anonymous said...

i have actually been having trouble to publish labels,
considering that i had my computer system cleanded out & dealt with I have actually been having trouble trying to
make tags.

my weblog: xerox phaser 8560mfp d

Anonymous said...

pls fwd me the link of the video clip.

Here is my website; Xerox phaser 8560 maintenance kit

Anonymous said...

I have actually produced my mailing list of addresses for Christmas just like the video reveals using MS word 2010 without any problems.
I could print one label every web page or I can publish the exact same tag on the
web page 30 times. I wish to print my list of various address on the web page so I have 30 different tags
to mail. I can easily not receive that finished the label area.
If I print with the regular visiting file, then print, I acquire the file
to print out but not formatted for the sort of labels I am making use of.
I just do not see how I can do the different address labels to publish in the label tab.

Thank you,.

My webpage xerox phaser 8560 solid ink

Anonymous said...

Yes, you can do this IF your Christmas card listing
joins database format AND you understand how to work with
Mail Merge in your word processor. Or else, this is the thrust for my
suggestion. Yes, it takes some time in advance the first year, however
afterward it is birthday cake.

Here is my page; blog.chitradip.com

Anonymous said...

Truly Interesting. Thanks for the Info. I like your site.


Feel free to visit my web-site ... xerox phaser 8560 ink

Anonymous said...

Nice blog here! Additionally your site rather a lot up very fast!
What web host are you the usage of? Can I get your associate link on your host?
I wish my site loaded up as fast as yours lol

Have a look at my page - hultquist jewellery stockists

Anonymous said...

Interestingly, I'm currently obtaining a limitcheck error on an HP4700- less than 2 years old! )Our now inoperative 4600 never had this issue when printing the specific very same file!

Here is my web-site - xerox phaser 8560 maintenance kit

Anonymous said...

Issue address with Samsung ML-1520 on WIN 8 Pro
64 bit.
Thanks to you !!!!!!
Superb !
!!!!!

Stop by my web page: xerox phaser 8560mfp

Anonymous said...

Are you aware that coverage amount, Make sure you
to acquire a quantity that at the very least equals the
estimated replacement cost in your home. However the options are yours.
Meanwhile, setting up a inventory of this personal
belongings at home can help you determine the right amount
insured in your personal estate.

Visit my website - contemporary silver jewellery :: ::

Anonymous said...

Those are really pretty!

Here is my homepage; ,cheap pretty earrings ()

Anonymous said...

Link exchange is nothing else except it is just placing the other person's weblog link on your page at proper place and other person will also do similar in support of you.

My web site xerox 8560 ink

Anonymous said...

i have been having trouble to print tags, because i had my pc cleanded out & worked on
I have been having problem attempting to make labels.


Also visit my blog - xerox phaser 8560 ink sticks **

Anonymous said...

I AM LOOKING FOR 47 INCH LED OR LCD TO BUY THE BEST DEAL CAN U SUGGEST ME WITH RATES

My web blog LG 42 LS56 Series []

Anonymous said...

Many thanks for composing. All the responses are in the video .
.. watch carefully and you will certainly be printing labels in no time!
Many thanks for stopping by!

my site :: xerox phaser 8560 maintenance kit []

Anonymous said...

Hello, yeah this post is in fact fastidious and I have learned lot of things from it on the topic of blogging.
thanks.

Feel free to visit my homepage :: xerox 8560 solid ink

Anonymous said...

Hi, this weekend is nice in support of me, for the reason that this moment i am reading this impressive informative piece
of writing here at my house.

My website ... LG 42LS5600 Review

Anonymous said...

Hi there, I wish for to subscribe for this blog to take hottest updates, therefore where can i do it please help out.


My web blog :: xerox 8560mfp d

Anonymous said...

I'm not sure exactly why but this site is loading very slow for me. Is anyone else having this issue or is it a problem on my end? I'll check back later on
and see if the problem still exists.

my website; xerox 8560 mfp

Anonymous said...

we prefer samsung laser printer driver.

Feel free to visit my web site; Xerox phaser 8560dn (www.trojanifsc.net)

Anonymous said...

FAB NECKLACE!LIKING BOTH PAGES

Check out my web blog: danon jewellery stockists

Anonymous said...

... and a breakthrough in to "4D" printing.

Also visit my weblog: xerox phaser 8560 manual

Anonymous said...

Love the jewellery. Am liking' both pages.

Also visit my site silver jewellery manufacturer

Anonymous said...

Sir, pls send out that video clip to my email I.D. It will
certainly be help ful 2 make pcb easy. Thankyou.

my web page :: xerox phaser 8560 error codes

Anonymous said...

In some cases the simplest means to removed
installed control sequences is to copy and insert the afflicted section to notepad, tidy up the text you desire protected,
then content and paste it back.

my site - xerox phaser 8560 ink

Anonymous said...

Useful information. Lucky me I discovered your web site unintentionally, and
I am surprised why this accident did not took place earlier!
I bookmarked it.

Review my homepage - xerox 8560dn