[hibernate-dev] multi-tenancy and ConnectionProvider

Steve Ebersole steve at hibernate.org
Wed Mar 23 17:58:09 EDT 2011


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



More information about the hibernate-dev mailing list