一些事务传播不适用于Spring / Hibernate 4

时间:2014-08-29 13:31:51

标签: spring hibernate transactions

我正在将应用程序从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拒绝创建没有有效事务的会话,那么将会话边界与会话而不是事务对齐是很困难的。会话及其持久化上下文不应与开放事务相关联。

1 个答案:

答案 0 :(得分:0)

通过实现CurrentSessionContext来解决这个问题,SpringSessionContextpublic 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}}。

希望这有助于其他人。