Tuesday, 5 June 2012

Hibernate Session Scope Strategy 1/3 Theory

This series of article is about handling synchronization of domain object life cycle by Hibernate.
Some parts of it are simplified for the convenience of the blog.

Those are the strategies how to handle scopes of Hibernate Session: we may say Session Scope Strategy, Session Holding Strategy, Open Session Strategy, etc.
This explanation is based by Hibernate + Spring Frameworks.

A Hibernate Session with Spring Framework closes at the same time a transaction session syncs with finished. And the synchronization of an entity (domain object) with SessionFactory comes to be broken(*1).

  *1 For a sync of an entity with SessionFactory to come to be broken is called as to 'detach.' Such a object is called as an 'detached object.'

When using Lazy Loading (this is the default setting of Hibernate), after a transaction finished, you execute a getter method of an entity, a LazyInitializationException occurs:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)

Leaving it be, it comes to be harmful.
  1. You cannot get a property on demand(i.e. you cannot use Lazy Loading on view rendering).
  2. When you use a domain object between several screens, you have to get a domain object by event even if that domain objects are the same(i.e. Optimistic locking between screen events comes to be manual).
If your system is distributed and business process and view process are divided by a protocol(e.g. SOAP), you have to live with it by beforehand executing getter methods, or eagar-fetching properties. But if your system is in one physical server, it is preferable to resolve it.

That is to say, if you can make Hibernate Session open while you want to get properties of domain objects, this problem will be resolved. Which means you take around Hibernate Session as open.

There are two strategies to take around Hibernate Session as open.
  1. Open Session In View (OSIV)
  2. Flow Managed Persistence (FMP)
1. OSIV is the design strategy to make Session open from one request-to-response. This can be set without any other implementation if you use OpenSessionInViewFilter which Spring Framework provides. This is correspond to harmful 1.
2. FMP is that to make Session open within the scope you set as you want between screens. This can be set without any other implementation if you use Spring Web Flow(SWF). you can make Session open by the scope which SWF defines. This is correspond to harmful 2.

To wrap up, the following:

Hibernate Session Scope Strategy Patterns
Strategy PatternScopeProblem to resolveMeans
Open Session In View
1 request (Session-per-request)errors related to LazyLoading occur on rendering a viewSessionInViewFilter class which Spring Framework provides
Flow Managed Persistent(FMP)1 conversation(Session-per-conversation)You have to synchronize manually a domain object on a process between screens/buttons(long Unit of Work)(e.g. session.reflesh()) Spring Web Flow(SWF)

If you don't use SWF, you should implement FMP manually.
Otherwise you use JBoss Seam on EJB Server, you can do as well as FMP.

Then when you use SWF, you'd better use FMP.

How to set them actually is the next.


No comments:

Post a Comment