我的Google-fu让我失望,所以我希望你可以帮忙
我构建一些web服务是使用scala和anorm进行数据库访问的play框架
我的一个调用是更新数据库中的现有行 - 即运行像
这样的查询UPDATE [Clerks]
SET [firstName] = {firstName}
,[lastName] = {lastName}
,[login] = {login}
,[password] = {password}
WHERE [id] = {id}
我的方法接收一个职员对象但是所有参数都是可选的(当然除了id),因为他们可能只希望像这样更新行的一列
UPDATE [Clerks]
SET [firstName] = {firstName}
WHERE [id] = {id}
所以我希望这个方法能够检查哪些职员参数被定义并构建了' SET'相应的更新声明的一部分
似乎应该有更好的方法,而不是通过职员对象的每个参数,检查它是否已定义并构建查询字符串 - 但到目前为止我还无法找到关于该主题的任何内容
有没有人有任何建议如何最好地处理
答案 0 :(得分:1)
正如评论者提到的那样,似乎无法实现 - 您必须自己构建查询字符串。
我发现围绕这个缺乏的例子并且需要更多的时间来解决这个问题(我是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()
}
}
这可能不是最好的方法,但我发现它非常易读,参数在准备好的声明中得到妥善处理。
希望这可以使遇到类似问题的人受益
如果有人想要提供改进,我们将非常感激地收到
答案 1 :(得分:0)
大约从2.6.0版开始,这可以通过其http://playframework.github.io/anorm/#generated-parameter-conversions宏直接用定理实现。
这是我的例子:
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