使用hibernate参数设置Postgresql架构

时间:2017-04-13 02:54:50

标签: java postgresql hibernate

我有一个使用模式分隔租户的多租户应用程序。我的连接池不支持多租户开箱即用(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有关,因为如果我对其进行硬编码,查询运行正常。

1 个答案:

答案 0 :(得分: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()方法仅用于调试目的,以方便(例如用于记录目的)