[hibernate-dev] multi-tenancy and ConnectionProvider

Steve Ebersole steve at hibernate.org
Fri Mar 25 13:10:50 EDT 2011


Here is the other issue with "separate hierarchies"...

Code that deals with connections now becomes more complicated, having to first 
see if there is a SpecializedConnectionProvider and if so grab a connection 
from it, otherwise check the ConnectionProvider.

Obviously there are techniques to work around that like making all Connection 
access route back through the Session which could expose a singular contract 
for getting a connection.  Then the "dirtiness" could be contained to just 
that "thing".


On Wednesday, March 23, 2011, at 04:58 pm, Steve Ebersole wrote:
> Well I think I am leaning towards a "parameter object" no matter what we do
> otherwise.  So call this param object interface ConnectionOptions.  It
> would have a single method today (err, tomorrow when I write all this :)
> to get the tenant id.
> 
> The tenant id is really associated with the session.  Either session
> implements that interface or hands it off to a delegate it manages, but
> thats the "scope"... the session.
> 
> So in your examnple, you would inject the entitymanager's session with the
> proper tenant id.  Ideally I want this to be specified up front when the
> session is opended to make sure there is no possibility of changing it mid-
> stream, but that further relies on
> http://opensource.atlassian.com/projects/hibernate/browse/HHH-2860
> 
> Anyway, in thinking about this sme more I think the way I really like is
> this:
> 
> 1) ConnectionProvider remains as is
> 2) introduce a new provider contract (names as always are preliminary):
> 
> public interface SpecializedConnectionProvider extends ConnectionProvider {
>     public static interface ConnectionOptions {
>         public String getTenantIdentifier();
>     }
> 
>     public Connection getSpecializedConnection(ConnectionOptions);
>     public void releaseSpecializedConnection(ConnectionOptions,
> Connection); }
> 
> Having SpecializedConnectionProvider extend ConnectionProvider addressed
> another issue I encountered when implementing this.  How do you account for
> situations where you need *some* connection?  Like when reading
> java.sql.DatabaseMetaData on "startup".  The other option for that is to
> not have SpecializedConnectionProvider extend ConnectionProvider (so they
> are back to distinct hierarchies) and adding an extra method to
> SpecializedConnectionProvider.  This additional method would either give
> access to a connection with out providing tenant information or if
> obtaining java.sql.DatabaseMetaData is deemed the only acceptable use case
> there then just have a method to scrape that info passing back
> DatabaseMetaData is not an option if that is the decision because of
> java.sql.DatabaseMetaData#getConnection
> 
> Also, I was not sure if there is really a need for a specialized "release
> this connection" method in the case where SpecializedConnectionProvider
> extends ConnectionProvider.  There is still the
> ConnectionProvider#closeConnection method.  Now obviously if the
> herarchies are distinct we would need release capability on both...
> 
> On Wednesday, March 23, 2011, at 04:24 pm, Chris Bredesen wrote:
> > But 3 is how it's done today since we don't have the other solutions.
> > So yeah it's magical, but people do manage to make it work.  I will
> > concede that it is not always perceived as straightforward, however.
> > 
> > Something to think about in the grander scheme of things is how someone
> > would deal with obtaining a tenant-specific connection when resource
> > injection is in use.  #3 solves this but what about #1 and #2?  There
> > are some pretty neat things that I can envision wrt CDI but I haven't
> > thought through what the implementations would look like.
> > 
> > @Inject @TenantSpecific @UserDatabase private EntityManager em;
> > 
> > How would you drill the tenant information into the CP?
> > 
> > -CB
> > 
> > On 03/23/2011 04:25 PM, Adam Warski wrote:
> > > I think for a user the best option (easiest to understand) would be 1).
> > > 
> > > 3) is too magical. 2) is putting everything in one sack.
> > > 
> > > Adam
> > > 
> > > On Mar 22, 2011, at 10:21 PM, Steve Ebersole wrote:
> > >> reference
> > >> http://opensource.atlassian.com/projects/hibernate/browse/HHH-5697
> > >> 
> > >> For multi-tenancy implemented by sepaerate schema we need the ability
> > >> to tell the ConnectionProvider about the tenant for the given
> > >> getConnection() request. I really see 3 approaches to this:
> > >> 
> > >> 1) Have 2 hierarchies here.  The current ConnectionProvider contract
> > >> remains the same.  Add a new MultiTenantConnectionProvider with
> > >> methods accounting for tenant
> > >> 2) Just alter the ConnectionProvider contract to pass information in.
> > >> If we go this route I prefer the "parameter object" pattern where we
> > >> pass in ConnectionOptions interface (see issue).
> > >> 3) Use contextual lookup.  ConnentionProviders interested in (or
> > >> capable of understanding) mulit-tenancy would perform some kind of
> > >> "contextual" (ThreadLocal, etc) lookup for the needed information.
> > >> 
> > >> Thoughts?  Discussions?
> > >> 
> > >> ---
> > >> Steve Ebersole<steve at hibernate.org>
> > >> http://hibernate.org
> > >> _______________________________________________
> > >> hibernate-dev mailing list
> > >> hibernate-dev at lists.jboss.org
> > >> https://lists.jboss.org/mailman/listinfo/hibernate-dev
> > 
> > _______________________________________________
> > hibernate-dev mailing list
> > hibernate-dev at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
> 
> ---
> Steve Ebersole <steve at hibernate.org>
> http://hibernate.org

---
Steve Ebersole <steve at hibernate.org>
http://hibernate.org



More information about the hibernate-dev mailing list