Thread:
 A working strategy 
 tpischke   19 Jan 2007, 11:07 

Comment
Prev. thread 
 Next thread
 
Prev. posting 
 Next posting
From: tpischke (19 Jan 2007, 11:07) Replies: 0, Views: 17344
Subject: A working strategy
Lots of good information and food for thought on this page.  

We've been using Hibernate in combination with a complex two-tier Swing
Application for a little over two years now.  In that time, we've had
more than our share of LazyInitializationExceptions,
NonUniqueObjectExceptions, and all the other usual baddies.

To provide some background, our product is a Desktop Publishing
application with over 1500 java classes and 30+ persistent classes. 
Most of our persistent classes tie into the same object graph with a
Book as the top level element.  

So not a trivial use case, especially given the concerns on this wiki. 
However, we've hit upon a strategy that is working well (for us), and I
would shudder to even think of ever going back to trying to implement
persistence via JDBC.

We don't use the Humongous Session pattern above, mostly because such
usage was frowned upon in Hibernate in Action, and because I dislike the
memory-usage implications.  When I read about StaleObjectExceptions, I
am even less inclined to try it.

We do use a Single-Session pattern in the sense that only a single
session is ever active at any given time, which is doled out via our
HibernateUtil, and abstracted behind a DaoManager.

We synchronize all access to the session so that only a single thread
can ever access the session concurrently.  Thus DB access via Swing
Event Thread or via DB Worker Thread (or any other thread) must wait in
line to use the single session.  Since we keep our transactions short
and sweet, this doesn't lead to any lag problems.

We use auto-commit mode for database reads, since such reads are VERY
common, and usually initiated by subtle user interaction.  Trying to
wrap such reads in transactions would be a very complex task with little
real benefit.

All Database WRITES on the other hand are very carefully defined and
wrapped in specific transaction boundaries, each starting a new session
(closing the old session if necessary, since we only allow one session
to exist at any given time), and defining an explicit transaction.

And here is the crux of our approach:  Whenever a database update is
required, we lock() or update() the relevant object graphs into the *new
session*, do our work on the objects, and save via the DaoManager. 
Cascades are all carefully configured for update and lock cascades so
that we typically just lock() a single top level object, update it, 
save it, and commit.

Care must be taken if more than one object graph is involved, since
NonUniqueObjectExceptions can arise when during the lock().  A deep
knowledge of the object model, cascade semantics, and particularly and
circular references is needed to avoid this sort of issue.  Keeping the
session scope as small as possible, and attaching the smallest piece of
the object graph needed also helps.

In summary, though we have had many difficulties and issues, Hibernate
has worked out very well for us, eliminating mountains of JDBC code, and
with performance outstripping our previous JDBC model by orders of
magnitude.  

We are still looking for ways to improve things however.  Our
synchronization code is not very well encapsulated in all cases for
instance, since it is often necessary to handle synchronization at a
higher logical level than possible inside the DaoManager.
Prev. thread 
 Next thread
 
Prev. posting 
 Next posting
© Copyright 2006, Red Hat Middleware, LLC. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc. [Privacy Policy]