gpt4 book ai didi

java - 尽管使用 OSIV,Spring 事务划分仍会导致新的 Hibernate session

转载 作者:行者123 更新时间:2023-11-30 09:56:36 25 4
gpt4 key购买 nike

我将 Hibernate 与 OpenSessionInViewInterceptor 结合使用,这样单个 Hibernate session 将用于整个 HTTP 请求(或者我希望如此)。问题是 Spring 配置的事务边界导致创建新 session ,所以我遇到了以下问题(伪代码):

  • 从标记为@Transactional(propagation = Propagation.SUPPORTS, readOnly = false) 的方法开始
  • Hibernate session #1 开始
  • 调用DAO方法更新对象foo; foo 被加载到 session #1 的 session 缓存中
  • 调用另一个方法来更新 foo.bar,这个被标记为@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
    • 事务划分导致当前事务同步暂停,暂时解除当前Hibernate session 的绑定(bind)
    • Hibernate session #2 启动,因为当前没有 session
    • 更新 foo 上的字段栏(将 foo 加载到 session 缓存 #2 中);坚持DB
    • 事务完成,方法返回, session #1 恢复
  • 调用另一个方法来更新 foo 上的另一个字段
    • 从 session 缓存 #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 session 暂停,即使 OpenSessionInViewInterceptor 正在使用中也是如此。

当 session 未绑定(bind)时,我在日志中看到以下内容:

[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]

最佳答案

首先,您的 openSessionInViewInterceptor必须有一个 sessionFactory注入(inject),否则它不能完成它的工作:

<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>

此外,还有一个名为 singleSession 的属性- 它是 true默认情况下,但调试它的值以防万一。

然后,如果使用 Spring-MVC,则必须为 SimpleUrlHandlerMapping 配置拦截器(或您正在使用的任何一个),以便它可以实际应用:

<property name="interceptors">
<list>
<ref bean="openSessionInViewInterceptor"/>
</list>
</property>

如果使用其他任何东西,我认为你必须使用 <aop> 来定义它标签(您使用的是什么网络框架?)

关于java - 尽管使用 OSIV,Spring 事务划分仍会导致新的 Hibernate session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2271147/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com