Open Session In View Design Tradeoffs
The Open Session in View (OSIV) pattern gives rise to different opinions in the Java development community. Let’s go over OSIV and some of the pros and cons of this pattern.
The problem
The problem that OSIV solves is a mismatch between the Hibernate concept of session and it’s lifecycle and the way that many server-side view technologies work.
In a typical Java frontend application the service layer starts by querying some of the data needed to build the view. The remaining data needed can be lazy-loaded later, with the condition that the Hibernate session remains open – and there lies the problem.
Between the moment that the service layer method finishes it’s execution and the moment that the view is rendered, Hibernate has already committed the transaction and closed the session.
When the view tries to lazy load the extra data that it needs, if finds the Hibernate session closed, causing a LazyInitializationException.
The OSIV solution
OSIV tackles this problem by ensuring that the Hibernate session is kept open all the way up to the rendering of the view – hence the name of the pattern.
Because the session is kept open, no more LazyInitializationExceptions occur. The session or entity manager is kept open by means of a filter that is added to the request processing chain.
In the case of JPA the OpenEntityManagerInViewFilter will create an entity manager at the beginning of the request, and then bind it to the request thread.
The service layer will then be executed and the business transaction committed or rolled back, but the transaction manager will not remove the entity manager from the thread after the commit.
When the view rendering starts, the transaction manager will then check if there is already an entity manager binded to the thread, and if so use it instead of creating a new one.
After the request is processed, the filter will then unbind the entity manager from the thread.
The end result is that the same entity manager used to commit the business transaction was kept around in the request thread, allowing the view rendering code to lazy load the needed data.
Going back to the original problem
Let’s step back a moment and go back to the initial problem: the LazyInitializationException. Is this exception really a problem? This exception can also be seen as a warning sign of a wrongly written query in the service layer.
When building a view and it’s backing services, the developer knows upfront what data is needed, and can make sure that the needed data is loaded before the rendering starts.
Several relation types such as one-to-many use lazy-loading by default, but that default setting can be overridden if needed at query time using the following syntax:
select p FROM Person p left join fetch p.invoices
This means that the lazy loading can be turned off on a case by case basis depending on the data needed by the view.
OSIV in projects I’ve worked
In projects I have worked that used OSIV, we could see via query logging that the database was getting hit with a high number of SQL queries, sometimes to the point that developers had to turn off the Hibernate SQL logging.
The performance of these application was impacted, but it was kept manageable using second-level caches, and due to the fact that these where intranet-based applications with a limited number of users.
Pros of OSIV
The main advantage of OSIV is that it makes working with ORM and the database more transparent:
- Less queries need to be manually written
- Less awareness is required about the Hibernate session and how to solve LazyInitializationExceptions.
Cons of OSIV
OSIV seems to be easy to misuse and can accidentally introduce N+1 performance problems in the application. On projects I’ve worked OSIV did not work out well in the long-term.
The alternative of writing custom queries that eager fetch data depending on the use case is manageable and turned out well in other projects I’ve worked.
Alternatives to OSIV
Besides the application-level solution of writing custom queries to pre-fetch the needed data, there are other framework-level aproaches to OSIV.
The Seam Framework was built by some of the same developers as Hibernate , and solves the problem by introducing the notion of conversation.
Reference: | Open Session In View Design Tradeoffs from our JCG partner Aleksey Novik at the The JHades Blog blog. |