我正在将应用程序从3.3升级到Hibernate 4.2。我们还使用了Spring 3.1.3(我们现在无法及时更新)。
我的部分单元测试现在失败
org.hibernate.HibernateException: No Session found for current thread
SpringSessionContext中的。在错误的上下文中定义<tx:annotation-driven />
或者缺少CGLIB库的情况下,这不是问题。大多数测试都有效,这意味着在大多数情况下,事务代理正在运行。
现在失败的情况似乎是使用NOT_SUPPORTED,NEVER和SUPPORTED传播类型。无论出于何种原因,SpringSessionContext都不会在这些情况下创建会话。
我们的用例有时要求事务边界不要严格按照方法边界排列,并且会话有时会比事务更长。在Spring 3 / Hibernate 3的情况下,会话上下文绑定到本地线程,即使没有启动事务,对SessionFactory.getCurrentSession()
的调用也会返回会话实例。这是我希望在Hibernate 4案例中仍然存在的行为。
有没有人知道这方面的解决方法?如果Spring拒绝创建没有有效事务的会话,那么将会话边界与会话而不是事务对齐是很困难的。会话及其持久化上下文不应与开放事务相关联。
答案 0 :(得分:0)
通过实现CurrentSessionContext
来解决这个问题,SpringSessionContext
是public class ClassLoaderSpringSessionContext implements CurrentSessionContext {
private final SessionFactoryImplementor sessionFactory;
private final SpringSessionContext sessionContext;
public ClassLoaderSpringSessionContext(final SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory; // This is actually some class loading logic that isn't important to this transaction problem.
this.sessionContext = new SpringSessionContext(this.sessionFactory);
}
@Override
public Session currentSession() throws HibernateException {
try {
return sessionContext.currentSession();
} catch (HibernateException e) {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
Session session = this.sessionFactory.openSession();
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
session.setFlushMode(FlushMode.MANUAL);
}
SessionHolder sessionHolder = new SessionHolder(session);
TransactionSynchronizationManager
.registerSynchronization(new SpringSessionSynchronization(sessionHolder,
this.sessionFactory));
TransactionSynchronizationManager.bindResource(this.sessionFactory, sessionHolder);
sessionHolder.setSynchronizedWithTransaction(true);
return session;
} else {
throw new HibernateException(
"Could not obtain transaction-synchronized Session for current thread");
}
}
}
}
的包装,并借用了一些代码更改,使其成为Spring Framwork 4 +:
SpringSessionSynchronization
ClassLoaderSpringSessionContext
是Spring 4中的包私有类,因此我还必须将其作为私有内部类的版本提取到{{1}}。
希望这有助于其他人。