代码之家  ›  专栏  ›  技术社区  ›  Georg Leber

PostgreSQL使用search_path进行多租户

  •  1
  • Georg Leber  · 技术社区  · 9 年前

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

    我使用JavaEE 7和Wildfly 8.2.0。我创建了一个MultiTenantConnection Provider,它使用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语句正在返回另一个用户表。我必须为表显式设置模式名称,否则我查询了错误的表。

    声明:

    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足以查询数据。

    1 回复  |  直到 9 年前
        1
  •  0
  •   Georg Leber    9 年前

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