Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
播放Scala Anorm动态SQL进行更新查询_Scala_Playframework_Anorm - Fatal编程技术网

播放Scala Anorm动态SQL进行更新查询

播放Scala Anorm动态SQL进行更新查询,scala,playframework,anorm,Scala,Playframework,Anorm,我的Google fu让我失望了,所以我希望你能帮我 我正在构建一些Web服务,它是使用scala和anorm进行数据库访问的play框架 我的一个调用是更新数据库中的一个现有行,即运行如下查询 UPDATE [Clerks] SET [firstName] = {firstName} ,[lastName] = {lastName} ,[login] = {login} ,[password] = {password} WHERE [id] = {id} 我的方法接收一个

我的Google fu让我失望了,所以我希望你能帮我

我正在构建一些Web服务,它是使用scala和anorm进行数据库访问的play框架

我的一个调用是更新数据库中的一个现有行,即运行如下查询

UPDATE [Clerks]
   SET [firstName] = {firstName}
  ,[lastName] = {lastName}
  ,[login] = {login}
  ,[password] = {password}
 WHERE [id] = {id}
我的方法接收一个clerk对象,但所有参数都是可选的(当然id除外),因为它们可能只希望像这样更新行的一列

UPDATE [Clerks]
   SET [firstName] = {firstName}
 WHERE [id] = {id}
因此,我希望该方法检查定义了哪些clerk参数,并相应地构建update语句的“SET”部分

似乎应该有更好的方法,而不是遍历clerk对象的每个参数,检查它是否已定义并构建查询字符串——但到目前为止,我还没有找到关于这个主题的任何内容


有没有人对如何最好地处理这个问题有什么建议?正如评论员所说,这似乎是不可能的-您必须自己构建查询字符串

我发现这方面的例子并不多,解决这一问题所花费的时间比它应该的要多(我对scala和play框架不熟悉,所以这是一个常见的主题)

最后,我实现了以下内容:

override def updateClerk(clerk: Clerk) = {
  var setString: String = "[modified] = {modified}"
  var params: collection.mutable.Seq[NamedParameter] = 
     collection.mutable.Seq(
            NamedParameter("modified", toParameterValue(System.currentTimeMillis / 1000)), 
            NamedParameter("id", toParameterValue(clerk.id.get)))

  if (clerk.firstName.isDefined) {
    setString += ", [firstName] = {firstName}"
    params = params :+ NamedParameter("firstName", toParameterValue(clerk.firstName.getOrElse("")))
  }
  if (clerk.lastName.isDefined) {
    setString += ", [lastName] = {lastName}"
    params = params :+ NamedParameter("lastName", toParameterValue(clerk.lastName.getOrElse("")))
  }
  if (clerk.login.isDefined) {
    setString += ", [login] = {login}"
    params = params :+ NamedParameter("login", toParameterValue(clerk.login.getOrElse("")))
  }
  if (clerk.password.isDefined) {
    setString += ", [password] = {password}"
    params = params :+ NamedParameter("password", toParameterValue(clerk.password.getOrElse("")))
  }
  if (clerk.supervisor.isDefined) {
    setString += ", [isSupervisor] = {supervisor}"
    params = params :+ NamedParameter("supervisor", toParameterValue(clerk.supervisor.getOrElse(false)))
  }

  val result = DB.withConnection { implicit c =>
    SQL("UPDATE [Clerks] SET " + setString + " WHERE [id] = {id}").on(params:_*).executeUpdate()
  }
}
这可能不是最好的方法,但是我发现它可读性很强,并且参数在准备好的语句中得到了正确处理

希望这能让遇到类似问题的人受益


如果有人想提供改进,我们将非常感谢他们,因为大约2.6.0版anorm可以直接使用他们的宏

以下是我的例子:

case class UpdateLeagueFormInput(transferLimit: Option[Int], transferWildcard: Option[Boolean], transferOpen: Option[Boolean])
val input = UpdateLeagueFormInput(None, None, Some(true))

val toParams: ToParameterList[UpdateLeagueFormInput] = Macro.toParameters[UpdateLeagueFormInput]
val params = toParams(input)
val dynamicUpdates = params.map(p => {
  val snakeName = camelToSnake(p.name)
  s"$snakeName = CASE WHEN {${p.name}} IS NULL THEN l.$snakeName ELSE {${p.name}} END"
})
val generatedStmt = s"""UPDATE league l set ${dynamicUpdates.mkString(", ")} where league_id = ${league.leagueId}"""
SQL(generatedStmt).on(params: _*).executeUpdate()
制作:

UPDATE league l set transfer_limit = CASE WHEN null IS NULL THEN l.transfer_limit ELSE null END, transfer_wildcard = CASE WHEN null IS NULL THEN l.transfer_wildcard ELSE null END, transfer_open = CASE WHEN true IS NULL THEN l.transfer_open ELSE true END where league_id = 26;
注:

  • camelToSnake函数只是我自己的(解析器行有一个明显的ColumnNaming.SnakeCase,但我找不到类似的参数解析)

  • 我的示例字符串插入{league.leagueId},当它也可以将其作为一个参数时

  • 最好避免空字段的冗余集,但是我认为这是不可能的,而且在我看来
    clean code/messy auto-generated sql
    >
    messy code/clean auto-generated sql


我不确定是否有,因为对于批量更新/插入,人们往往也会构建查询字符串。您可以根据可用值动态准备SQL语句的字符串,将此语句传递给
SQL(…)
,然后传递参数。看看医生,你有没有找到更好的?您是否有机会分享
TopParameterValue
的定义?您好@Brad,从来没有找到更好的-将更新代码以包含TopParameterValue Hey@BradUrani-实际上我不需要添加代码-TopParameterValue是anorm包的一部分,所以您只需要“导入anorm.ParameterValue.\u':-)