Spring / Hibernate下的多个会话工厂
在我需要在同一实例中支持多个数据库以支持多租户的情况下,我得到了一个要求。每个数据库都有一个相同的架构。用户通过从列表中选择登录到特定的数据库,所有后续调用将转到该DB,直到他们注销。
我想根据客户端提供的参数在单个HibernateDaoTemplate中热交换会话工厂。
我可以在热交换数据源(以及与此相关的所有事务问题)上找到很多东西,但是我想热交换会话工厂以保留每个缓存的所有缓存。
最简单的方法是什么?为DaoTemplate配置HotSwappableTarget?谁能指出我的操作示例?
解决方案
如果所有数据库都是相同的,那么我建议使用一个SessionFactory并为DataSource和Cache提供我们自己的实现,这些实现实际上是"承租人感知的"。 (实施这些操作相当简单:只需维护一个租户ID映射->真实缓存/真实数据源,然后将所有调用委托给相应的调用)。配置单个SessionFactory以使用支持租户的缓存和数据源。 ThreadLocal可用于使当前请求的租户ID可用于需要了解该请求的任何代码。
在成功支持多租户之前,我已经使用了这种方法。
我们还可以查看Hibernate Shards项目:
http://www.hibernate.org/414.html
...的重点是在Hibernate Core中增加对水平分区的支持。它尚未涵盖完整的Hibernate API,但确实支持其中的很大一部分(可能不足或者不足以满足需求)。当然,他们正在努力实现全面覆盖。
在我以前工作的地方,我们按照本指南通过ThreadLocal进行了此操作。我们只是使用了一个SessionFactory,并根据用户可以在登录时更改的会话变量交换了它的数据源。我不记得确切的详细信息,但是如果我们有兴趣,我可以为我们的实现提供更多信息。
话虽这么说,但我以前工作场所中的家伙现在正在从这种方法转向建立分片数据库。绝对是一个更优雅的解决方案,我建议我们看一下。
从HibernateDaoSupport扩展DAO类,然后调用setSessionFactory()方法,以进行数据库的热交换
我还通过ThreadLocal尝试了缓存提供程序,而困难的部分是对缓存进行热交换,我们必须确保SessionFactory没有与其关联的任何活动会话。现在,我认为有一个更好的解决方案:通过使用Spring 3 Java配置,我们可以动态创建可识别租户的SessionFactory,并让Spring为我们执行缓存管理。