Spring transaction demarcation causes new Hibernate session despite use of OSIV

Posted by Kelly Ellis on Stack Overflow See other posts from Stack Overflow or by Kelly Ellis
Published on 2010-02-16T07:05:54Z Indexed on 2010/04/03 22:13 UTC
Read the original article Hit count: 442

Filed under:
|
|
|
|

I'm using Hibernate with OpenSessionInViewInterceptor so that a single Hibernate session will be used for the entire HTTP request (or so I wish). The problem is that Spring-configured transaction boundaries are causing a new session to be created, so I'm running into the following problem (pseudocode):

  • Start in method marked @Transactional(propagation = Propagation.SUPPORTS, readOnly = false)
  • Hibernate session #1 starts
  • Call DAO method to update object foo; foo gets loaded into session cache for session #1
  • Call another method to update foo.bar, this one is marked @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
    • Transaction demarcation causes suspension of current transaction synchronization, which temporarily unbinds the current Hibernate session
    • Hibernate session #2 starts since there's no currently-existing session
    • Update field bar on foo (loading foo into session cache #2); persist to DB
    • Transaction completes and method returns, session #1 resumes
  • Call yet another method to update another field on foo
    • Load foo from session cache #1, with old, incorrect value of bar
    • Update field foo.baz, persist foo to DB
    • foo.bar's old value overwrites the change we made in the previous step

Configuration looks like:

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

I've done some debugging and figured out exactly where this is happening, here is the stack trace:

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  

I can't figure out why transaction boundaries (even "nested" ones - though here we're just moving from SUPPORTS to REQUIRED) would cause the Hibernate session to be suspended, even though OpenSessionInViewInterceptor is in use.

When the session is unbound, I see the following in my logs:

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

© Stack Overflow or respective owner

Related posts about java

Related posts about hibernate