背景
我正在开发一款未来的多租户Web应用程序,需要支持数千个用户。该应用程序是基于Java的Play! MVC框架、JPA/Hibernate和PostgreSQL构建的。
我观看了Guy Naor在Rails中编写多租户应用上的演讲,在其中他谈到了几种多租户方法(随着列表的下降,数据隔离程度降低):
- 每个客户都有一个单独的数据库
- 一个数据库,为每个客户分别设置模式和表(表命名空间)。
- 一个数据库,有1组带有客户ID列的表。
我选择了第二种方法,其中某种形式的用户ID会从请求中解析出来,然后用于访问该用户的tablespace。在进行任何查询之前,会给出一个postgres SET search_path TO customer_schema,public
命令,以确保查询的目标是客户的表。在控制器方法中使用@Before
控制器注释很容易实现这一点(这是Guy在他的rails示例中使用的方法)。在postgres中,search_path的作用与操作系统中的$PATH
完全相同;太棒了!
所有这些听起来都很棒,但我立即遇到了在JDBC/Hibernate/JPA堆栈上实现它的困难,因为似乎没有一种方法可以在运行时动态切换模式。
问题
如何在运行时使JDBC或Hibernate支持动态切换postgres模式?
似乎数据库连接是由连接工厂静态配置的(参见:使用hibernate管理一个数据库上的多个模式)。我发现类似的问题有相似的答案,即为每个用户使用多个SessionFactorys,但由于我了解SessionFactorys是重量级对象,因此通过这种方式支持数百个甚至成千上万的用户是不可行的。
我还没有完全致力于上述第2种方法,但我也还没有完全放弃第3种方法。