Upgrading to Hibernate 4.1 and the "infamous" HibernateTemplate

Okay, So this is what I actually did, I don't know if this is the best solution for this problem, but under our circumstances, and since I was looking for the most localized solution, it seemed best to me.

I have extended the springframework.orm.hibernate3.HibernateTemplate and created a new MyHibernateTemplate. The new template's main role is to override the doExecute method that most of the hibernate3.HibernateTemplate eventually lead to, and also supply some of the functionality that was provided by the old SessionFactoryUtils (like isSessionTransactional and applyTransactionTimeout).

The new doExecute replicates the logic of the old one, but instead of SessionFactoryUtils.getNewSession to get a session it first try to look for an open session getSessionFactory().getCurrentSession() :

boolean newSessionOpened = false;
Session session;

if (enforceNewSession){
    session = SessionFactoryUtils.openSession(getSessionFactory());
    newSessionOpened = true;
} else {
    try {
        // look for an open session
        session = getSessionFactory().getCurrentSession();
    }
    catch (HibernateException ex) {
        try {
            // if there isn't an open session, open one yourself
            session = getSessionFactory().openSession();
            newSessionOpened = true;
        } catch (HibernateException e) {
            throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
        }
    }
}

// is the open session, is a session in a current transaction?
boolean existingTransaction = (!enforceNewSession &&
        (!isAllowCreate() || isSessionTransactional(session, getSessionFactory())));

You just need to close this session manually:

    finally {
    // if session was used in an existing transaction restore old settings
    if (existingTransaction) {
        //logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
        disableFilters(session);
        if (previousFlushMode != null) {
            session.setFlushMode(previousFlushMode);
        }
    }
    // if not and a new session was opened close it
    else {
        // Never use deferred close for an explicitly new Session.
        if (newSessionOpened) {
            SessionFactoryUtils.closeSession(session);
            //_log.info("Closing opened Hibernate session");
        }
    }

I'm Trying keep this answer short, but if there are any questions I can elaborate further about this problem.


Check out this section in the docs. It says that SessionFactory.getCurrentSession() is pluggable and there is a ThreadLocalSessionContext implementation that keeps the 'current session' in the ThreadLocal rather than a JTA transaction. ThreadLocalSessionContext will also close the Session at the end of the hibernate Transaction created from that Session, so you don't have to worry about closing the Session yourself.

With regards to introducing regression bugs, upgrading a library will always have it's risks, especially so when it is something as core to your application as hibernate. The only advice I can give is to ensure your test suite has decent coverage before the upgrade. After all, that's the job of your test suite - to catch regression bugs.