Reputation: 12140
I am asking me how I should deal with background threads performing database-involving tasks in my Hibernate/Spring web application.
Currently I am using the following interceptor, so I can annotate my thread run methods with @OpenSession and a session should be opened. This should also work for RMI requests for example or any other method that is called without a session being opened. However, I am not sure if the code is correct, I face the problem that sometimes the sessions are just not closed and kept open forever.
@Around("@annotation(openSession)")
public Object processAround(ProceedingJoinPoint pjp, OpenSession openSession) throws Throwable {
boolean boundResource = false;
Session session = null;
// Bind the session to the thread, if not already done
if(TransactionSynchronizationManager.getResource(sessionFactory) == null) {
log.debug("Opening Hibernate Session in method "+pjp.getSignature());
session = SessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
boundResource = true;
}
// Invoke the annotated method
Object ret;
try {
ret = pjp.proceed();
}
catch(Throwable t) {
// Rethrows the Exception but makes sure the session will be closed
SessionFactoryUtils.closeSession(session);
log.debug("Closing Hibernate Session in method (Exception thrown) "+pjp.getSignature());
throw t;
}
// If a resourc was bound by this method call, unbind it.
if(boundResource) {
//SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
session.flush();
SessionFactoryUtils.closeSession(session);
log.debug("Closing Hibernate Session in method "+pjp.getSignature());
}
return ret;
}
Upvotes: 3
Views: 2302
Reputation: 9893
Yes, your suggested solution should work (I've done something very similar myself). If you only use @Transactional
, you'll get a new EntityManager
for each transaction, which isn't necessarily optimal if your background thread has many transactions.
Upvotes: 1
Reputation: 6289
Hibernate sessions and JDBC connections are not thread safe. You should stick with a connection and a session per thread.
Upvotes: 1