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<st...@hibernate.org> > > >> http://hibernate.org > > >> _______________________________________________ > > >> hibernate-dev mailing list > > >> hibernate-dev@lists.jboss.org > > >> https://lists.jboss.org/mailman/listinfo/hibernate-dev > > > > _______________________________________________ > > hibernate-dev mailing list > > hibernate-dev@lists.jboss.org > > https://lists.jboss.org/mailman/listinfo/hibernate-dev > > --- > Steve Ebersole <st...@hibernate.org> > http://hibernate.org --- Steve Ebersole <st...@hibernate.org> http://hibernate.org _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev