【问题标题】:Setting Postgresql schema with hibernate parameters使用休眠参数设置 Postgresql 模式
【发布时间】:2017-04-13 02:54:50
【问题描述】:

我有一个使用模式来分隔租户的多租户应用程序。我的连接池不支持开箱即用的多租户(Dropwizard) - 所以我试图在检索时手动设置租户的架构。但是,我收到一个 SQL 语法错误。

代码:

NativeQuery fpq = this.getSessionFactory()
                          .getCurrentSession()
                          .createNativeQuery("SET schema=?");
fpq.setParameter(1, tenantSchema);
fpq.executeUpdate();

错误:

DEBUG org.hibernate.SQL: SET schema=?
TRACE org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [1] as [VARCHAR] - [myapplication_client1]
WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper: SQL Error: 0, SQLState: 42601
ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper: ERROR: syntax error at or near "$1"
  Position: 12

我也尝试过"SET search_path=?""SET search_path TO ?",结果相同。这似乎很简单,我做错了什么? tenantSchema 变量是使用不可信字符串生成的,因此正确构建参数而不是手动连接 SQL 非常重要。

更新:通过调试器,我已经验证 Hibernate 正确地将语句转换为 SET schema 'myapplication_client1' - 但它仍然失败,我不知道为什么。它肯定与setParameter 有关,因为如果我对其进行硬编码,查询运行良好。

【问题讨论】:

  • 您应该能够修改您的 sql 以包含 schema 例如select colA from myschema.mytable;
  • @ScaryWombat 不幸的是,这不是一个选择。租户设置逻辑必须在一个类中。重要的是每个查询只在其自己的租户内运行,并且依靠每个语句来手动设置架构会带来太大的风险

标签: java postgresql hibernate


【解决方案1】:

您不能在准备好的语句中将标识符作为参数传递。模式名称是一个标识符,就像一个表名一样,你也不能select * from ?

您必须将参数连接到您的查询:

NativeQuery fpq = this.getSessionFactory()
                          .getCurrentSession()
                          .createNativeQuery("SET schema=" + tenantSchema);
fpq.executeUpdate();

由于这是来自“不受信任”来源的参数,因此您需要在执行此操作之前验证它是否正确。一种简单的方法是使用 DatabaseMetaData.getSchemas() 检索所有模式并验证参数是否是其中之一。


无关的:

Hibernate 正确地将语句转换为SET schema 'myapplication_client1'

不,Hibernate 没有转换任何东西。这正是 Postgres JDBC 驱动程序实现 PreparedStatement.toString() 方法的方式。这并不意味着它是发送到数据库的查询。 toString() 方法只是为了方便调试而存在(例如,用于日志记录)

【讨论】:

    猜你喜欢
    • 2013-04-28
    • 2015-09-24
    • 1970-01-01
    • 1970-01-01
    • 2013-06-30
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多