我正在将应用程序从 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 拒绝在没有有效事务的情况下创建会话,则很难将会话边界与会话而不是事务对齐。会话及其持久性上下文不应与开放事务绑定。
通过实施解决了这个问题CurrentSessionContext
这是一个围绕 a 的包装SpringSessionContext
并借用了 Spring Framework 4+ 中的一些代码更改:
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");
}
}
}
}
SpringSessionSynchronization
是 Spring 4 中的一个包私有类,所以我还必须将其版本作为私有内部类拉出ClassLoaderSpringSessionContext
.
希望这对其他人有帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)