【问题标题】:PostgreSQL using search_path for multi tenancyPostgreSQL 使用 search_path 进行多租户
【发布时间】:2015-10-08 22:28:19
【问题描述】:

我正在开发一个使用 PostgreSQL 作为数据库的多租户 Web 应用程序,因为它支持一个数据库实例中的模式。但是我遇到了一个问题,为租户设置了 search_path。

我正在使用 JavaEE 7 和 Wildfly 8.2.0。我创建了一个 MultiTenantConnectionProvider,它使用 DataSourceConnectionProvider 加载配置的 DataSource。

检索连接的方法将search_path设置为给定的tenantId:

@Override
public Connection getConnection(String tenantId) throws SQLException
{
    Connection con = getAnyConnection();
    try
    {
        con.createStatement().execute("SET search_path = '" + tenantId + "'");
        LOG.info("Using " + tenantId + " as database schema");
    }
    catch (SQLException ex)
    {
        throw new HibernateException("Could not alter connection for specific schema");
    }
    return con;
}

对于第一次测试,我总是返回相同的tenantId“customer1”。

在 Postgres 上,我创建了一个用户,它有自己的数据库和一个模式“customer1”。我有一个实体user,定义如下:

@Entity
@Table(name = "user")
public class User implements Serializable
{
    @Id
    @GeneratedValue
    private Long id;
    @Column(unique = true, nullable = false)
    private String username;
    private String firstname;
    private String lastname;
    private String gender;
    @Column(unique = true, nullable = false)
    private String email;
    @Column(nullable = false)
    private byte[] password;
    private String passwordResetToken;
    @Column(nullable = false)
    private byte[] salt;
...
}

我已经在模式“customer1”中创建了表。现在我的问题是表用户的选择语句正在返回另一个用户表。我必须用表显式设置架构名称,否则我会查询错误的表。

声明:

select * from user; -> current_user name: user1

返回:

| current_user name |
--------------------
| "skedflex"        |

声明:

select * from customer1.user;

返回:

| id | username | firstname | lastname | ... |
----------------------------------------------
| 1  | johnnie  | John      | Doe      | ... |

无法在查询中使用模式名称,因为该值是在运行时确定的,而我正在使用 JPA。因此在运行时查询执行期间没有办法插入模式名称。

我已经预料到,search_path 足以查询数据。

【问题讨论】:

  • postgresql.org/docs/9.4/interactive/sql-alteruser.html 您可以设置search_path 每个用户
  • 你不能挂钩连接池,以便在获取连接时调用回调吗?此外,您已经进行了日志记录:日志记录是否显示您的 SET 实际运行?如果您在postgresql.conf 中启用log_statement = 'all',您会看到预期的语句运行吗?尝试在postgresql.conf 中设置log_line_prefix…。
  • 我已经用 pgAdmin 3 测试了这个 alos,首先运行命令 set search_path = 'customer1'; 然后尝试选择 id = 1 的用户:select * from user where id = 1; 但它给了我在我的问题中提到的错误结果.

标签: postgresql jpa multi-tenant java-ee-7


【解决方案1】:

我发现我的设置有问题。 在 PostgreSQL 中,user 是一个关键字,不能创建具有此名称的表,除非用户用引号转义:"user"。我已将表名更改为 user_account 并且查询按预期工作。

【讨论】:

    猜你喜欢
    • 2012-11-02
    • 2015-07-03
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2015-06-01
    • 2014-12-22
    • 1970-01-01
    相关资源
    最近更新 更多