private static ISession DoGetSession(
ISessionFactory sessionFactory, IInterceptor entityInterceptor,
IAdoExceptionTranslator adoExceptionTranslator, bool allowCreate)
{
AssertUtils.ArgumentNotNull(sessionFactory, "sessionFactory", "SessionFactory can not be null");
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.GetResource(sessionFactory);
if (sessionHolder != null && !sessionHolder.IsEmpty)
{
// pre-bound Hibernate Session
ISession session = null;
if (TransactionSynchronizationManager.SynchronizationActive &&
sessionHolder.DoesNotHoldNonDefaultSession)
{
// Spring transaction management is active ->
// register pre-bound Session with it for transactional flushing.
session = sessionHolder.ValidatedSession;
if (session != null && !sessionHolder.SynchronizedWithTransaction)
{
log.Debug("Registering Spring transaction synchronization for existing Hibernate Session");
TransactionSynchronizationManager.RegisterSynchronization(
new SpringSessionSynchronization(sessionHolder, sessionFactory, adoExceptionTranslator, false));
sessionHolder.SynchronizedWithTransaction = true;
// Switch to FlushMode.AUTO if we're not within a read-only transaction.
FlushMode flushMode = session.FlushMode;
if (FlushMode.Never == flushMode &&
!TransactionSynchronizationManager.CurrentTransactionReadOnly)
{
session.FlushMode = FlushMode.Auto;
sessionHolder.PreviousFlushMode = flushMode;
}
}
}
else
{
// No Spring transaction management active -> simply return default thread-bound Session, if any
// (possibly from OpenSessionInViewModule)
session = sessionHolder.ValidatedSession;
}
if (session != null)
{
return session;
}
}
ISession sess = OpenSession(sessionFactory, entityInterceptor);
// Set Session to FlushMode.Never if we're within a read-only transaction.
// Use same Session for further Hibernate actions within the transaction.
// Thread object will get removed by synchronization at transaction completion.
if (TransactionSynchronizationManager.SynchronizationActive)
{
log.Debug("Registering Spring transaction synchronization for new Hibernate Session");
SessionHolder holderToUse = sessionHolder;
if (holderToUse == null)
{
holderToUse = new SessionHolder(sess);
}
else
{
holderToUse.AddSession(sess);
}
if (TransactionSynchronizationManager.CurrentTransactionReadOnly)
{
sess.FlushMode = FlushMode.Never;
}
TransactionSynchronizationManager.RegisterSynchronization(
new SpringSessionSynchronization(holderToUse, sessionFactory, adoExceptionTranslator, true));
holderToUse.SynchronizedWithTransaction = true;
if (holderToUse != sessionHolder)
{
TransactionSynchronizationManager.BindResource(sessionFactory, holderToUse);
}
}
// Check whether we are allowed to return the Session.
if (!allowCreate && !IsSessionTransactional(sess, sessionFactory))
{
CloseSession(sess);
throw new InvalidOperationException ("No Hibernate Session bound to thread, " +
"and configuration does not allow creation of non-transactional one here");
}
return sess;
}