def insertToTableSQLQuery(tableName: String, columnDefinitions: Seq[ColumnDefinition], rowData: ListBuffer[Any]): Future[Int] = db.run {
val columns = columnDefinitions.map(_.name).mkString(", ")
sqlu"insert into #$tableName(#$columns) values (#${rowData(0)}, #${rowData(1)}, #${rowData(2)}, #${rowData(3)}, #${rowData(4)});"
}
字符串
如何使用Scala构建SQL查询,以便在Slick中动态绑定或插值rowData值?
def insertToTableSQLQuery(tableName: String, columnDefinitions: Seq[ColumnDefinition], rowData: ListBuffer[Any]): Future[Int] = db.run {
val columnNames = columnDefinitions.map(_.name).mkString(", ")
val placeholders = List.fill(rowData.length)("?").mkString(", ")
sqlu"insert into #$tableName(#$columnNames) values (#${rowData.map(_ => "?").mkString(", ")});".bind(rowData: _*)
}
型
我尝试使用参数绑定,但这是抛出一个错误。
错误
value bind is not a member of slick.sql.SqlAction[Int,slick.dbio.NoStream,slick.dbio.Effect]
[error] possible cause: maybe a semicolon is missing before `value bind`?
[error] .bind(rowData: _*)
[error]
型
1条答案
按热度按时间dwthyt8l1#
在plain sql中,有两种方法可以在运行时注入值。
Slick中的普通SQL查询是通过使用
sql
、sqlu
和tsql
插值器的字符串插值构建的。它们可以通过Slick配置文件中的标准api._
导入获得:字符串
任何注入到查询中的变量或表达式都会在结果查询字符串中转换为绑定变量。它不会直接插入到查询字符串中,因此不会有SQL注入攻击的危险。您可以在这里看到这一点:
型
此方法生成的SQL语句始终相同:
型
虽然大多数参数应该作为绑定变量插入到SQL语句中,但有时需要将文字值直接拼接到语句中,例如对表名进行抽象或运行动态生成的SQL代码。为此,您可以在所有插值器中使用
#$
而不是$
,如以下代码所示:型
因此,对于表或列等文字值,您需要使用
#$
和$
作为变量值。在您的情况下,代码应该类似于
型
这不足以解决问题,因为在编译代码时,您会得到以下错误
型
这意味着slick不知道如何绑定
Any
类型的值。Slick为Int,Boolean,String,Doubel,BigDecimal等常见值提供了隐式SetParameter。解决这个问题的一个方法是创建你自己的
implicit SetParameter[Any] = ???
,我建议你在任何scala项目中尽量避免使用Any
,除非你真的需要。另一个选择是使用
case class
或Tuple
来代替List[Any]
。case类更容易使用,因为你可以为每个字段设置一个名称,而当你想要访问元组时,你需要知道值的位置。case类也更容易重构。