【问题标题】:Hibernate and Multi-Tenant Database using Schemas in PostgreSQL在 PostgreSQL 中使用模式的休眠和多租户数据库
【发布时间】:2012-01-11 01:34:30
【问题描述】:

背景

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

我在 Writing Multi-tenant Applications in Rails 上观看了 Guy Naor 的演讲,他在其中谈到了多租户的一些方法(数据隔离随着列表的下降而减少):

  1. 每个客户都有一个单独的数据库
  2. 一个数据库,每个客户都有单独的架构和表(表命名空间)。
  3. 一个数据库,其中包含一组带有客户 ID 列的表。

我选择了方法 #2,其中某种用户 ID 从请求中解析出来,然后用于访问该用户表空间。在进行任何查询之前会给出 postgres SET search_path TO customer_schema,public 命令,以确保客户的表是查询的目标。这可以通过 Play! 的控制器方法中的 @Before 控制器注释轻松完成(这是 Guy 在他的 rails 示例中使用的方法)。 postgres 中的 search_path 与操作系统中的$PATH 完全相同;太棒了!

这一切听起来都很棒,但我立即在 JDBC/Hibernate/JPA 堆栈上实现它时遇到了困难,因为似乎没有办法在运行时动态切换模式。

问题

如何让 JDBC 或 Hibernate 支持在运行时动态切换 postgres 架构?

似乎数据库连接是由连接工厂静态配置的(参见:How to manage many schemas on one database using hibernate)。我发现了与每个用户使用多个 SessionFactory 的类似答案的类似问题,但由于我了解 SessionFactory 是重量级对象,因此您无法支持数百个用户,更不用说数千个用户了,走这条路。

我还没有完全致力于上面的方法#2,但我也没有完全放弃它而转向方法#3。

【问题讨论】:

    标签: java hibernate postgresql jdbc playframework


    【解决方案1】:

    你可以执行命令

    SET search_path TO customer_schema,public
    

    在同一个连接/会话/事务中,根据需要经常进行。这只是另一个命令,例如SELECT 1;。更多内容请关注manual here

    当然,您也可以为每个用户预设search_path

    ALTER ROLE foo SET search_path=foo, public;
    

    如果每个用户或其中许多用户都有与其用户名匹配的架构,您可以简单地使用default setting in postgresql.conf

    search_path="$user",public;
    

    更多设置search_path的方法在这里:
    How does the search_path influence identifier resolution and the "current schema"

    【讨论】:

    • 这是最简单的解决方案,因为我现在已经切换到 MyBatis 并且可以完全控制 SQL 语句。
    【解决方案2】:

    从 Hibernate 4.0 开始,在鉴别器 (customerID)、架构和数据库级别上原生支持多租户。见源代码here,单元测试here

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

    【讨论】:

    • 从 Hibernate 4.0 开始,鉴别器级别不支持多租户。预计在 5.0 中。
    • Kinara,您能否提供有关这种缺乏支持的文档? OP 中引用的谈话似乎表明它受到支持......以及jboss documentation
    • 查看同一文档中 16.3 的最后一段,其中讨论了鉴别器方法 - “该策略尚未在 Hibernate 4.0 和 4.1 中实现。计划在 5.0 中支持它。 "
    • @AgileYogi 5.0 的工作开始了吗?我在 github 上只看到 4.3。
    • 5.0 鉴别器级别的多租户事件尚未完成。
    【解决方案3】:

    虽然按模式进行分片很常见,但请参阅 Apartment gem 作者的this post,其中涵盖了一些缺点。

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

    【讨论】:

      猜你喜欢
      • 2014-12-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-18
      • 1970-01-01
      • 2022-09-27
      • 2015-06-08
      • 2014-02-01
      • 2015-08-25
      相关资源
      最近更新 更多