views:

3872

answers:

5

I have been given a requirement where I need to support multiple databases in the same instance, to support multi-tenancy. Each DB has an identical schema. The user logs into a specific database by choosing from a list, and all subsequent calls will go to that DB until they log out.

I want to hot swap the session factory inside a single HibernateDaoTemplate based on a parameter supplied by the client.

I can find lots of stuff on hot-swapping data sources (and all the transaction issues associated with that) but I want to hot swap session factories - retaining all the caching for each.

What's the easiest way to do this? Configure a HotSwappableTarget for the DaoTemplate? Can anyone point me to samples on how to do this?

+2  A: 

If all the databases are identical, then I can suggest using a single SessionFactory and providing your own implementations for the DataSource and Cache that are actually "tenant-aware". (Implementing these is fairly trivial: just maintain a map of tenant id -> real cache/real datasource and then delegate all calls to the appropriate one). Configure the single SessionFactory to use your tenant-aware Cache and DataSource. A ThreadLocal can be used to make the tenant ID of the current request available to any code that needs to know about it.

I have used this approach before successfully to support multi-tenancy.

alasdairg
Good idea - but how do you switch in the tenant-aware cache? All you can do is configure a cache provider, and hibernate uses this under the covers to create a cache. Maybe Implement a CacheProvider that in turn generates a tenant-aware cache wrapper?
Verdant
A: 

You could also take a look at the Hibernate Shards project:

http://www.hibernate.org/414.html

... which is focused on adding support for horizontal partitioning to the Hibernate Core. It does not yet cover the full Hibernate API, but does support a large portion of it (which may or may not be sufficient for your needs). Of course, they are working towards complete coverage.

alasdairg
+2  A: 

Where I used to work we did this via ThreadLocal following this guide. We just used one SessionFactory and swapped it's datasource based on a session variable the user could change while logged in. I don't remember the exact details, but if you're interested I can dig up some more information on our implementation.

That being said though, the guys at my former workplace are now moving away from this approach and towards a sharded database. Definitely a more elegant solution that I'd recommend you take a look at.

stian
A: 

extend your DAO class from HibernateDaoSupport, then invoke setSessionFactory() method, to do the hot swap of the databases

A: 

I also tried the cache provider via ThreadLocal and the difficult part was doing the hot swap on the cache, you have to make sure the SessionFactory does not have any active sessions associate with it. Now, I think there is a much better solution: by using the Spring 3 java configuration, you can create your tenant-aware SessionFactory dynamically and let Spring to do the cache management for you.

renfred