Hibernate和PostgreSQL中使用模式的多租户数据库

11

背景

我正在开发一款未来的多租户Web应用程序,需要支持数千个用户。该应用程序是基于Java的Play! MVC框架、JPA/Hibernate和PostgreSQL构建的。

我观看了Guy Naor在Rails中编写多租户应用上的演讲,在其中他谈到了几种多租户方法(随着列表的下降,数据隔离程度降低):

  1. 每个客户都有一个单独的数据库
  2. 一个数据库,为每个客户分别设置模式和表(表命名空间)。
  3. 一个数据库,有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种方法。

3个回答

7
你可以执行该命令。
SET search_path TO customer_schema,public

在同一连接/会话/事务中,您可以根据需要频繁地使用它。它只是另一个命令,就像 SELECT 1;。更多信息请参见此处的手册
当然,您也可以为每个用户预设search_path
ALTER ROLE foo SET search_path=foo, public;

如果每个用户或他们中的大多数都有与其用户名匹配的模式,则可以使用postgresql.conf中的默认设置: (参考链接)
search_path="$user",public;

在这里设置search_path的更多方法:
搜索路径如何影响标识符解析和“当前模式”


这是最简单的解决方案,因为我现在已经转换到 MyBatis,并且完全掌握了 SQL 语句的控制。 - Jesse

1

尽管按模式分片很常见,但请参阅来自Apartment gem作者的this post,其中涵盖了一些缺点。

在Citus中,我们通过上面列出的第3个选项进行分片,您可以在文档中的use-case guide中了解更多信息。


1

从Hibernate 4.0开始,多租户在鉴别器(客户ID)、模式和数据库级别上本地支持。请查看源代码这里和单元测试这里

困难在于,虽然单元测试的文件名为SchemaBasedMultitenancyTest,但实际使用的MultitenancyStrategy是Database。我找不到任何基于模式使其工作的示例,但也许单元测试足以进行...


2
从Hibernate 4.0开始,在鉴别器级别上不支持多租户。这在5.0中得到了支持。 - Thinkisto
Kinara,您能提供关于此缺乏支持的文档吗?OP中提到的讨论似乎表明它得到了支持...以及jboss文档 - therealmitchconnors
1
请查看同一文档中第16.3段的最后一段,其中讨论了鉴别器方法 - “截至Hibernate 4.0和4.1版本,该策略尚未实现。计划在5.0版本中支持它。” - Thinkisto
@AgileYogi已经开始5.0的工作了吗?我在github上只看到4.3。 - Blankman
5.0版本中的事件在鉴别器级别上的多租户尚未完成。 - leokom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接