Ok, here's my current wrapper method:
Code:
public static void executeInSession(HibernateSessionWork work) {
if (work == null)
throw new IllegalArgumentException("Work can not be null");
try {
//use thread bound session if it's available
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
boolean localSession = (sessionHolder == null);
Session session = SessionFactoryUtils.getSession(HibernateUtils.sessionFactory, localSession);
//if we created session locally, we need to bind it to thread
if (localSession) {
sessionHolder = new SessionHolder(session);
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
}
if (session != null) {
try {
//pass session factory to work
work.setSessionFactory(HibernateUtils.sessionFactory);
//do stuff that uses session
work.execute();
if (localSession)
session.flush();
} finally {
//cleanup
work.setSessionFactory(null);
if (localSession) {
session.close();
TransactionSynchronizationManager.unbindResource(sessionFactory);
}
}
} else
throw new RuntimeException("Could not get Hibernate session");
} catch (HibernateException e) {
throw SessionFactoryUtils.convertHibernateAccessException(e);
}
}
And the skeleton class for work is:
Code:
public abstract class HibernateSessionWork {
private static final Log logger = Logging.getLog(HibernateSessionWork.class);
private SessionFactory sessionFactory;
void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/**
* Get an instance of HibernateTemplate, bound to current session.
*
* @return
*/
public final HibernateTemplate getHibernateTemplate() {
return new HibernateTemplate(this.sessionFactory, false);
}
/**
* Get the current Hibernate session.
*
* @return
*/
public final Session getSession() {
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
return sessionHolder.getSession();
}
/**
* To be used with <code>HibernateUtils.executeInSession()</code>. Encapsulate
* a piece of work that requires a Hibernate session, without actually
* doing session management.
*
* To actually access Hibernate, implementation should get instances of Session and
* HibernateTemplate using <code>getSession()</code> and <code>getHibernateTemplate</code>.
*
* If this method throws an exception, session will NOT be flushed to database
* (but it will be closed, still).
*/
public abstract void execute();
}
Does this seem to be right? I'm a bit concerned about the lines that call TransactionSychronizationManager - if sessions are managed locally, there are no transactions and calling TSM sounds scary to me.. Am I potentially breaking something because of (un)bindResource() calls?