新起的线程须要绑定Hibernate session。才干在新线程中使用事务和延迟载入等功能,否则会曝出no session异常。
解决的方法:
new Runnable() {
@Override
public void run() {
// ----------绑定session到当前线程------------
SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
boolean participate = ConcurrentUtil.bindHibernateSessionToThread(sessionFactory);
// ---------你的业务---------------
<pre name="code" class="java">// ----------关闭session------------
ConcurrentUtil.closeHibernateSessionFromThread(participate, sessionFactory);
}
}
bindHibernateSessionToThread方法:
public static boolean bindHibernateSessionToThread(SessionFactory sessionFactory) {
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
// Do not modify the Session: just set the participate flag.
return true;
} else {
Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.MANUAL);
SessionHolder sessionHolder = new SessionHolder(session);
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
}
return false;
}
closeHibernateSessionFromThread方法
public static void closeHibernateSessionFromThread(boolean participate, Object sessionFactory) {
if (!participate) {
SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(sessionHolder.getSession());
}
}
事务边界则由aop或者Transactional标记来控制。演示样例代码仅仅是保证具备事务性的方法在须要的时候能从当前线程中获得session对象。
上述代码大部分截取自Spring的OpenSessionInViewFilter。