In a Spring 3 application, I\'m trying to implement multi-tenancy via Hibernate 4\'s native MultiTenantConnectionProvider and CurrentTenantIdentifierResolver. I see that the
Foreward: Although I accepted this answer which (will) contains code, please upvote Darren's answer if you think this was useful. He's the reason I was able to solve this at all.
Okay, so here we go....
As Darren pointed out, this is really an issue with SessionFactory's instantiating a Session improperly. If you were to instantiate the session manually, you have no issue. eg:
sessionFactory.withOptions().tenantIdentifier(tenant).openSession();
However, the @Transactional
annotation causes the SessionFactory to open a session with sessionFactory.getCurrentSession()
, which does not pull the tenant identifier from the CurrentTenantIdentifierResolver
.
Darren suggested opening the Session manually in the DAO layer, but this means that each DAO method will have a locally scoped transaction. The better place to do this is on the service layer. Each service layer call (ie, doSomeLogicalTask()
) may call multiple DAO methods. It makes sense that each of these should be bound to the same transaction, as they're logically related.
Furthermore, I didn't like the idea of duplicating code in each service layer method to create and manage a transaction. Instead, I used AOP to wrap each method in my service layer with with the advice to instantiate a new Session
and handle the transaction. The aspect stores the current Session
in a TheadLocal
stack which can be accessed by the DAO layer for querying.
All of this work will allow the interfaces and implementations to stay identical to their bug-fixed counterparts, except one line in the DAO superclass that will get the Session
from the ThreadLocal
stack rather than the SessionFactory
. This can be changed once the bug is fixed.
I will post the code shortly, once I clean it up a little. If anybody sees any problems with this, do feel free to discuss below.