I'm trying to understand how Spring transaction manages Hibernate sessions/transactions, and how OpenSessionInViewFilter plays its role. As such, I've created several test cases on our current project. Just to make it clear, our application is working as expected but I'm just using it to test and understand how these things work. Our application is a web application, with OpenSessionInViewFilter configured, using a DataSourceTransactionManager, with Hibernate as the ORM, and a TransactionAwareDataSourceProxy to wrap the underlying datasource that is being managed by the TxManager and Hibernate session factory.
So far, this is my observation:
In a web application:
Scenario #1 - I removed OpenSessionInViewFilter from the web.xml - TransactionAwareDataSourceProxy wrapping the data source - Using DataSourceTransactionManager Result: When it goes through the AuthenticationFilter, I read some records from the database, and during this time, it complains "No Hibernate session bound to thread".
Scenario #2 - I removed OpenSessionInViewFilter from the web.xml - Using HibernateTransactionManager - But now I put it @Transactional on the AuthenticationFilter method being called. Result: When it goes through the AuthenticationFilter to read some records from the database, it didn't complain. But on other filters, it complained "No Hibernate session bound to thread" again.
Scenario #3 - Same with scenerio #1 - Tried adding the @Transactional on the method being called (Same with scenario #2) Result: When it goes through the AuthenticationFilter, I read some records from the database, and during this time, it complains "No Hibernate session bound to thread".
So, after analyzing this behavior and digging in HibernateTransactionManager, I noticed in the source code that HibernateTransactionManager tries to open a Hibernate session (in the absence of OpenSessionInViewFilter), that's why it was able to go through. Unlike using DataSourceTransactionManager where it doesn't know anything about the Hibernate Session. So based on this assumption, without OpenSessionInViewFilter, there's no Hibernate session created for the TransactionSynchronizationManager to retrieve, thus the "No Hibernate session bound to thread". Btw, my DAO is just using:
sessionFactory.getCurrentSession();
So, my (1) question is, is this assumption correct?
So is it HibernateTransactionManager creating the session (If OpenSessionInViewFilter is not configured)?
Based on this train of thought, I tried creating test cases in JUnit environment:
JUnit Scenario #1 - Ran using Spring JUnit with @Transactional on the test class level - TransactionAwareDataSourceProxy wrapping the data source - Using DataSourceTransactionManager Result: It didn't complain about "No Hibernate session bound to thread".
JUnit Scenario #2 - Ran using Spring JUnit with @Transactional on the test class level - Using HibernateTransactionManager Result: Works fine.
So, my (2) question is, why in a JUnit environment, it didn't complain about "No Hibernate session bound to thread" using JUnit scenario #1? But using the same setup in a web application, it did?
(3) What is really happening in the background? (4) How does the Hibernate session, spring transaction work hand in hand?
Please help! Have been trying to understand this for quite some time.
Thank you very much!
|