Upgrading to Hibernate 4.1 and the "infamous" HibernateTemplate
hibernate, java, spring
Solution
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.
Problem
I'm upgrading our project from Hibernate 3.0 to Hibernate 4.1.6. (And we are currently using spring 3.1) I read in many articles and in HibernateTemplate documentation, that since version 4.0 HibernateTemplate is not supported and that I should replace it's usage with calling `sessionFactory.getCurrentSession()` to get a session. Since this project was started with older version of Hibernate, where the use of `HibernateTemplate` was encouraged, we currently have 124 usages of `HibernateTemplate` across our project. I'm afraid that replacing all these occurrences with `sessionFactory.getCurrentSession()` might insert regression bugs in our project. In addition, there are some places where `HibernateTemplate` was used in a non-transactional context, where there is no 'current' session. What should I do in those cases? Open a new session and handle (close) it myself? That wasn't the case when I used `HibernateTemplate`. Do you have some good strategy addressing these issues? Thanks. Relevant reading: - Hibernate Vs. Spring - HibernateTemplate history - Hibernate Core Migration Guide - MIGRATING TO SPRING 3.1 AND HIBERNATE 4.1 - org.springframework.orm.hibernate3.HibernateTemplate