Refer the following example.
@Repository
public class ContactDAOImpl implements ContactDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
public List<Contact> findAll() {
Session session = sessionFactory.openSession();
return session.createQuery("from Contact").list();
}
}
Before it gets invoked the session.openSession()
, spring has already created a session for the thread via OpenEntityManagerInViewInterceptor
.
Even if I close the session manually (considering the answer) as below
@Override
public List<Contact> findAll() {
Session session;
try{
session = sessionFactory.openSession();
return session.createQuery("from Contact").list();
}finally{
if(session!=null){
session.close(); //logs says it is closed, but actually it gets closed via OpenEntityManagerInViewInterceptor, not by this call.
}
}
}
still Spring holds the session and close it via OpenEntityManagerInViewInterceptor
.
Appreciate very much if anyone explain me the use of Hibernate session in a Spring container.
And when to use openSession()
and getCurrentSession()
and when we should not use them?
Update:
Both the above examples are working fine. But why?
If I use the getCurrentSession()
with the configuration spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
, it also works fine.
Update2:
Here is the log output I get, when I use session.openSession()
. You will see at the end of the log, session (SessionImpl
) is about to be closed.
2017-03-01 10:28:31.106 DEBUG 6008 --- [io-8080-exec-10] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2017-03-01 10:28:31.106 TRACE 6008 --- [io-8080-exec-10] .i.SessionFactoryImpl$SessionBuilderImpl : Opening Hibernate Session. tenant=null, owner=org.hibernate.jpa.internal.EntityManagerImpl@445e7f4a
2017-03-01 10:28:31.107 TRACE 6008 --- [io-8080-exec-10] org.hibernate.internal.SessionImpl : Opened session at timestamp: 14883443111
2017-03-01 10:28:31.108 TRACE 6008 --- [io-8080-exec-10] org.hibernate.internal.SessionImpl : Setting flush mode to: AUTO
2017-03-01 10:28:31.109 TRACE 6008 --- [io-8080-exec-10] org.hibernate.internal.SessionImpl : Setting cache mode to: NORMAL
2017-03-01 10:28:31.110 DEBUG 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@445e7f4a] for JPA transaction
2017-03-01 10:28:31.110 DEBUG 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.sura2k.hbm.business.ContactServiceImpl.findAll]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
2017-03-01 10:28:31.111 DEBUG 6008 --- [io-8080-exec-10] o.s.jdbc.datasource.DataSourceUtils : Setting JDBC Connection [ProxyConnection[PooledConnection[conn9: url=jdbc:h2:mem:contactsdb user=SA]]] read-only
2017-03-01 10:28:31.112 DEBUG 6008 --- [io-8080-exec-10] o.h.e.t.internal.TransactionImpl : begin
2017-03-01 10:28:31.112 TRACE 6008 --- [io-8080-exec-10] j.i.AbstractLogicalConnectionImplementor : Preparing to begin transaction via JDBC Connection.setAutoCommit(false)
2017-03-01 10:28:31.112 TRACE 6008 --- [io-8080-exec-10] j.i.AbstractLogicalConnectionImplementor : Transaction begun via JDBC Connection.setAutoCommit(false)
2017-03-01 10:28:31.112 TRACE 6008 --- [io-8080-exec-10] cResourceLocalTransactionCoordinatorImpl : ResourceLocalTransactionCoordinatorImpl#afterBeginCallback
2017-03-01 10:28:31.113 TRACE 6008 --- [io-8080-exec-10] org.hibernate.internal.SessionImpl : Setting flush mode to: MANUAL
2017-03-01 10:28:31.113 DEBUG 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@34b8834a]
2017-03-01 10:28:31.114 TRACE 6008 --- [io-8080-exec-10] .i.SessionFactoryImpl$SessionBuilderImpl : Opening Hibernate Session. tenant=null, owner=null
2017-03-01 10:28:31.116 TRACE 6008 --- [io-8080-exec-10] org.hibernate.internal.SessionImpl : Opened session at timestamp: 14883443111
2017-03-01 10:28:31.116 TRACE 6008 --- [io-8080-exec-10] o.h.engine.query.spi.QueryPlanCache : Located HQL query plan in cache (from ContactEntity)
2017-03-01 10:28:31.117 TRACE 6008 --- [io-8080-exec-10] o.h.engine.query.spi.QueryPlanCache : Located HQL query plan in cache (from ContactEntity)
2017-03-01 10:28:31.117 TRACE 6008 --- [io-8080-exec-10] o.h.engine.query.spi.HQLQueryPlan : Find: from ContactEntity
2017-03-01 10:28:31.117 TRACE 6008 --- [io-8080-exec-10] o.hibernate.engine.spi.QueryParameters : Named parameters: {}
2017-03-01 10:28:31.118 DEBUG 6008 --- [io-8080-exec-10] org.hibernate.SQL : select contactent0_.contactid as contacti1_0_, contactent0_.email as email2_0_, contactent0_.name as name3_0_ from contact contactent0_
2017-03-01 10:28:31.119 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.ResourceRegistryStandardImpl : Registering statement [prep10: select contactent0_.contactid as contacti1_0_, contactent0_.email as email2_0_, contactent0_.name as name3_0_ from contact contactent0_]
2017-03-01 10:28:31.120 TRACE 6008 --- [io-8080-exec-10] o.h.e.jdbc.internal.JdbcCoordinatorImpl : Registering last query statement [prep10: select contactent0_.contactid as contacti1_0_, contactent0_.email as email2_0_, contactent0_.name as name3_0_ from contact contactent0_]
2017-03-01 10:28:31.121 TRACE 6008 --- [io-8080-exec-10] org.hibernate.loader.Loader : Bound [1] parameters total
2017-03-01 10:28:31.121 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.ResourceRegistryStandardImpl : Registering result set [rs23: org.h2.result.LocalResult@4e4e3165 columns: 3 rows: 0 pos: -1]
2017-03-01 10:28:31.121 TRACE 6008 --- [io-8080-exec-10] org.hibernate.loader.Loader : Processing result set
2017-03-01 10:28:31.121 TRACE 6008 --- [io-8080-exec-10] org.hibernate.loader.Loader : Done processing result set (0 rows)
2017-03-01 10:28:31.121 TRACE 6008 --- [io-8080-exec-10] org.hibernate.loader.Loader : Total objects hydrated: 0
2017-03-01 10:28:31.122 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.ResourceRegistryStandardImpl : Releasing statement [prep10: select contactent0_.contactid as contacti1_0_, contactent0_.email as email2_0_, contactent0_.name as name3_0_ from contact contactent0_]
2017-03-01 10:28:31.122 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.ResourceRegistryStandardImpl : Closing result set [rs23: org.h2.result.LocalResult@4e4e3165 columns: 3 rows: 0 pos: 0]
2017-03-01 10:28:31.122 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.ResourceRegistryStandardImpl : Closing prepared statement [prep10: select contactent0_.contactid as contacti1_0_, contactent0_.email as email2_0_, contactent0_.name as name3_0_ from contact contactent0_]
2017-03-01 10:28:31.123 TRACE 6008 --- [io-8080-exec-10] o.h.e.jdbc.internal.JdbcCoordinatorImpl : Starting after statement execution processing [ON_CLOSE]
2017-03-01 10:28:31.123 TRACE 6008 --- [io-8080-exec-10] o.h.e.i.StatefulPersistenceContext : Initializing non-lazy collections
2017-03-01 10:28:31.123 TRACE 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Triggering beforeCommit synchronization
2017-03-01 10:28:31.124 TRACE 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Triggering beforeCompletion synchronization
2017-03-01 10:28:31.124 DEBUG 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
2017-03-01 10:28:31.124 DEBUG 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@445e7f4a]
2017-03-01 10:28:31.124 DEBUG 6008 --- [io-8080-exec-10] o.h.e.t.internal.TransactionImpl : committing
2017-03-01 10:28:31.124 TRACE 6008 --- [io-8080-exec-10] cResourceLocalTransactionCoordinatorImpl : ResourceLocalTransactionCoordinatorImpl#beforeCompletionCallback
2017-03-01 10:28:31.124 TRACE 6008 --- [io-8080-exec-10] org.hibernate.internal.SessionImpl : SessionImpl#beforeTransactionCompletion()
2017-03-01 10:28:31.124 TRACE 6008 --- [io-8080-exec-10] .t.i.SynchronizationRegistryStandardImpl : SynchronizationRegistryStandardImpl.notifySynchronizationsBeforeTransactionCompletion
2017-03-01 10:28:31.124 TRACE 6008 --- [io-8080-exec-10] j.i.AbstractLogicalConnectionImplementor : Preparing to commit transaction via JDBC Connection.commit()
2017-03-01 10:28:31.124 TRACE 6008 --- [io-8080-exec-10] j.i.AbstractLogicalConnectionImplementor : Transaction committed via JDBC Connection.commit()
2017-03-01 10:28:31.124 TRACE 6008 --- [io-8080-exec-10] j.i.AbstractLogicalConnectionImplementor : LogicalConnection#afterTransaction
2017-03-01 10:28:31.124 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.ResourceRegistryStandardImpl : Releasing JDBC resources
2017-03-01 10:28:31.124 TRACE 6008 --- [io-8080-exec-10] j.i.AbstractLogicalConnectionImplementor : re-enabling auto-commit on JDBC Connection after completion of JDBC-based transaction
2017-03-01 10:28:31.126 TRACE 6008 --- [io-8080-exec-10] cResourceLocalTransactionCoordinatorImpl : ResourceLocalTransactionCoordinatorImpl#afterCompletionCallback(true)
2017-03-01 10:28:31.126 TRACE 6008 --- [io-8080-exec-10] .t.i.SynchronizationRegistryStandardImpl : SynchronizationRegistryStandardImpl.notifySynchronizationsAfterTransactionCompletion(3)
2017-03-01 10:28:31.126 TRACE 6008 --- [io-8080-exec-10] org.hibernate.internal.SessionImpl : SessionImpl#afterTransactionCompletion(successful=true, delayed=false)
2017-03-01 10:28:31.126 TRACE 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Triggering afterCommit synchronization
2017-03-01 10:28:31.126 TRACE 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Triggering afterCompletion synchronization
2017-03-01 10:28:31.126 TRACE 6008 --- [io-8080-exec-10] org.hibernate.internal.SessionImpl : Setting flush mode to: AUTO
2017-03-01 10:28:31.127 DEBUG 6008 --- [io-8080-exec-10] o.s.orm.jpa.JpaTransactionManager : Not closing pre-bound JPA EntityManager after transaction
2017-03-01 10:28:31.132 DEBUG 6008 --- [io-8080-exec-10] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2017-03-01 10:28:31.132 DEBUG 6008 --- [io-8080-exec-10] o.s.orm.jpa.EntityManagerFactoryUtils : Closing JPA EntityManager
2017-03-01 10:28:31.132 TRACE 6008 --- [io-8080-exec-10] org.hibernate.internal.SessionImpl : Closing session
2017-03-01 10:28:31.132 TRACE 6008 --- [io-8080-exec-10] o.h.e.jdbc.internal.JdbcCoordinatorImpl : Closing JDBC container [org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl@69c176d4]
2017-03-01 10:28:31.133 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.ResourceRegistryStandardImpl : Releasing JDBC resources
2017-03-01 10:28:31.133 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.LogicalConnectionManagedImpl : Closing logical connection
2017-03-01 10:28:31.133 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.ResourceRegistryStandardImpl : Releasing JDBC resources
2017-03-01 10:28:31.133 TRACE 6008 --- [io-8080-exec-10] o.h.r.j.i.LogicalConnectionManagedImpl : Logical connection closed
Also I tried to monitor this using VisualVM Profiler. After making 5 requests to http://localhost:8080/contact, I was able to see only one instance of SessionImpl
.
Also I have uploaded a simpler version here https://bitbucket.org/sura2k/tests which I used to test.