将模式名称作为变量传递给查询的最佳方法

时间:2015-03-13 08:50:49

标签: anorm string-interpolation

我有一个PlayFramework服务器(带有Anorm),它对具有多个模式的数据库进行操作,所有模式都使用相同的表。

我的“数据库访问”功能大部分都是:

def findById(zoneName: String, id: Long): Option[Employee] = {
    DB.withConnection { implicit connection =>
      SQL("""select *
          from """+zoneName+"""employee
          where employee._id = {id}"""
      .on(
          '_id -> id
        ).as(simpleParser.singleOpt)
    }
  }

但我知道这是一种错误的方法,因为它不是SQL-Injection安全的,当然在每个函数中编写都很繁琐。

我想使用字符串插值来纠正这一点,它适用于我的id变量,但不适用于zoneName

def findById(zoneName: String, id: Long): Option[Employee] = {
    DB.withConnection { implicit connection =>
      SQL"""select *
          from $zoneName.employee
          where employee._id = 1"""
      .as(simpleParser.singleOpt)
    }
  }

给我:

info] ! @6lenhal6c - Internal server error, for (GET) [/limbo/br/employee/1] ->
[info] 
[info] play.api.Application$$anon$1: Execution exception[[PSQLException: ERROR: syntax error at or near «$1»
[info]   Position: 25]]
[info]  at play.api.Application$class.handleError(Application.scala:296) ~[play_2.11-2.3.8.jar:2.3.8]
[info]  at play.api.DefaultApplication.handleError(Application.scala:402) [play_2.11-2.3.8.jar:2.3.8]
[info]  at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun$applyOrElse$4.apply(PlayDefaultUpstreamHandler.scala:320) [play_2.11-2.3.8.jar:2.3.8]
[info]  at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun$applyOrElse$4.apply(PlayDefaultUpstreamHandler.scala:320) [play_2.11-2.3.8.jar:2.3.8]
[info]  at scala.Option.map(Option.scala:146) [scala-library-2.11.5.jar:na]
[info] Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near «$1»
[info]   Position: 25
[info]  at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198) ~[postgresql-9.3-1102.jdbc4.jar:na]
[info]  at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927) ~[postgresql-9.3-1102.jdbc4.jar:na]
[info]  at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255) ~[postgresql-9.3-1102.jdbc4.jar:na]
[info]  at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561) ~[postgresql-9.3-1102.jdbc4.jar:na

使用${zoneName}进行测试,结果相同。

任何关于如何写这篇文章的帮助或建议都将不胜感激,谢谢你们!

1 个答案:

答案 0 :(得分:2)

使用Anorm字符串插值,任何$expression都将被提供一个参数,也就是说它是否是JDBC驱动程序引用的字符串。

如果要用字符串替换部分SQL语句(例如动态模式),可以使用串联,或者从最新版本(2.4.0-M3或2.3.8)开始使用语法#$expr

val table = "myTable"
SQL"SELECT * FROM #$table WHERE id=$id"
// SELECT * FROM myTable WHERE id=?