Skip to content

TransactionSynchronizationUtils.unwrapResourceIfNecessary() does not unwrap scoped SessionFactory [SPR-5671] #10342

@spring-projects-issues

Description

@spring-projects-issues

Eric Chen opened SPR-5671 and commented

Like so many before me, it all started with looking for a way to use Spring with Hibernate and multiple SessionFactories (multiple databases, each with different schema).

I Googled and found many discussions dating from around 2004 to 2007. The solution I opted for is outlined in the thread below - it involves creating a custom scope for a single SessionFactory proxy that delegates to the appropriate SessionFactory implementation based on a ThreadLocal variable.

http://forum.springsource.org/showthread.php?t=64382

The initial implementation worked fine for months, until for testing purposes we reduced the size of our database connection pools to 1. This exposed the bug TransactionSynchronizationUtils.unwrapResourceIfNecessary() is not unwrapping custom-scoped SessionFactories (because it does not implement InfrastructureProxy) before storing/fetching the Hibernate Session.

TransactionInterceptor stores the Hibernate Session using the custom-scope SessionFactory proxy:

[code]
Thread [main] (Suspended (breakpoint at line 438 in HibernateTransactionManager))
HibernateTransactionManager.doGetTransaction() line: 438
HibernateTransactionManager(AbstractPlatformTransactionManager).getTransaction(TransactionDefinition) line: 341
TransactionInterceptor(TransactionAspectSupport).createTransactionIfNecessary(TransactionAttribute, String) line: 263
TransactionInterceptor.invoke(MethodInvocation) line: 101
...
[/code]

However, Hibernate SessionFactoryImpl (via SpringSessionContext) looks for an existing session using itself - the real SessionFactory implementation. Therefore, it fails to find the Session created by TransactionInterceptor

[code]
Thread [main] (Suspended (breakpoint at line 139 in TransactionSynchronizationManager))
TransactionSynchronizationManager.getResource(Object) line: 139
SessionFactoryUtils.doGetSession(SessionFactory, Interceptor, SQLExceptionTranslator, boolean) line: 285
SessionFactoryUtils.doGetSession(SessionFactory, boolean) line: 258
SpringSessionContext.currentSession() line: 60
SessionFactoryImpl.getCurrentSession() line: 544
...
[/code]

Clearly, this is because TransactionInterceptor and SpringSessionContext are using different SessionFactory objects as keys in TransactionSynchronizationmanager.resources line: 82.

The need to unwrap certain proxied objects before using them as keys in a map was forseen - hence the use of TransactionSyncrhonizationUtils.unwrapResourceIfNecessary() line: 57.

It seems to me that this function should be expanded to include scoped AOP proxies.


Affects: 2.5.6

Referenced from: commits 2b962e7

1 votes, 3 watchers

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: dataIssues in data modules (jdbc, orm, oxm, tx)type: bugA general bug

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions