Today let’s discuss the interaction between multitenancy and the current session feature.
Multitenancy let’s you isolate
Session operations between different tenants.
This is useful to create a single application isolating different customers from one another.
The current session feature returns the same session for a given context, typically a (JTA) transaction. This facilitates the one session per view/transaction/conversation pattern and avoids the one session per operation anti-pattern.
Session session = sessionFactory.getCurrentSession(); // do some other work [...] // later in the same context (e.g. JTA Transaction) Session session2 = sessionFactory.getCurrentSession(); // semantically we have assert session == session2
The two features work well together, simply implement CurrentTenantIdentifierResolver. That will give Hibernate ORM the expected tenant id when the current session is created.
When discussing with Florian and the ToulouseJUG,
we exchanged on a small case where things might not work as you expect.
Hibernate ORM considers that, for a given context (e.g. transaction),
there can only be a single current
So if in the same context (e.g. transaction):
CurrentTenantIdentifierResolverimplementation returns different values of tenant id,
you will get a
However, it is sometimes useful to be able to reach several tenants from the same context. You have two options:
Manually create the
Implement a custom
You can use the
SessionFactory API to create a
Session for the tenant id you are looking for.
Session session1 = sessionFactory.withOptions() .tenantIdentifier( tenant1 ) ... .openSession(); Session session2 = sessionFactory.withOptions() .tenantIdentifier( tenant2 ) ... .openSession();
But you have to make sure to close these sessions. If you are used to CDI or Spring handling sessions for you, or if you rely on the current session feature to propagate the session across your stack, this might be annoying.
The alternative is to implement your own version of
avoid raising the
Session instances per both context and tenant id.
In practice, current sessions are stored in a
ConcurrentHashMap keyed by context identifier,
you just need to improve that part.
Start with JTASessionContext
and hack away!
We are currently discussing whether the default
should partition by tenant id or raise the exception.
If you have your opinion, chime in!
In the mean time, use one of the options above.