-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
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