【发布时间】:2011-01-17 06:54:18
【问题描述】:
我将 Hibernate 与 OpenSessionInViewInterceptor 一起使用,以便将单个 Hibernate 会话用于整个 HTTP 请求(或者我希望如此)。问题是 Spring 配置的事务边界导致创建新会话,所以我遇到了以下问题(伪代码):
- 从标记为 @Transactional(propagation = Propagation.SUPPORTS, readOnly = false) 的方法开始
- 休眠会话 #1 开始
- 调用DAO方法更新对象foo; foo 被加载到会话 #1 的会话缓存中
- 调用另一个方法更新foo.bar,这个标记为@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
- 事务划分导致当前事务同步暂停,这会暂时解除当前 Hibernate 会话的绑定
- 由于没有当前存在的会话,休眠会话 #2 开始
- 更新 foo 上的字段栏(将 foo 加载到会话缓存 #2);持久化到数据库
- 事务完成,方法返回,会话 #1 恢复
- 调用另一个方法来更新 foo 上的另一个字段
- 从会话缓存 #1 加载 foo,bar 的值旧且不正确
- 更新字段 foo.baz,将 foo 持久化到 DB
- foo.bar 的旧值会覆盖我们在上一步中所做的更改
配置如下:
<bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor" autowire="byName">
<property name="flushModeName">
<value>FLUSH_AUTO</value>
</property>
</bean>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="useTransactionAwareDataSource" value="true" />
<property name="mappingLocations">
<list>
<value>/WEB-INF/xml/hibernate/content.hbm.xml</value>
</list>
</property>
<property name="lobHandler">
<ref local="oracleLobHandler" />
</property>
<!--property name="entityInterceptor" ref="auditLogInterceptor" /-->
<property name="hibernateProperties"
ref="HibernateProperties" />
<property name="dataSource" ref="myDataSource" />
</bean>
我已经进行了一些调试并弄清楚了发生这种情况的确切位置,这是堆栈跟踪:
Daemon Thread [http-8080-1] (Suspended (entry into method doUnbindResource in TransactionSynchronizationManager))
TransactionSynchronizationManager.doUnbindResource(Object) line: 222
TransactionSynchronizationManager.unbindResource(Object) line: 200
SpringSessionSynchronization.suspend() line: 115
DataSourceTransactionManager(AbstractPlatformTransactionManager).doSuspendSynchronization() line: 620
DataSourceTransactionManager(AbstractPlatformTransactionManager).suspend(Object) line: 549
DataSourceTransactionManager(AbstractPlatformTransactionManager).getTransaction(TransactionDefinition) line: 372
TransactionInterceptor(TransactionAspectSupport).createTransactionIfNecessary(TransactionAttribute, String) line: 263
TransactionInterceptor.invoke(MethodInvocation) line: 101
ReflectiveMethodInvocation.proceed() line: 171
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 204
$Proxy14.changeVisibility(Long, ContentStatusVO, ContentAuditData) line: not available
我不明白为什么事务边界(即使是“嵌套”的边界——尽管这里我们只是从 SUPPORTS 移动到 REQUIRED)会导致 Hibernate 会话暂停,即使 OpenSessionInViewInterceptor 正在使用中。
当会话未绑定时,我在日志中看到以下内容:
[2010-02-16 18:20:59,150] DEBUG org.springframework.transaction.support.TransactionSynchronizationManager Removed value [org.springframework.orm.hibernate3.SessionHolder@7def534e] for key [org.hibernate.impl.SessionFactoryImpl@693f23a2] from thread [http-8080-1]
【问题讨论】:
标签: java hibernate spring session transactions