我在Play + Scala应用程序(2.5.x,2.11.11)中使用Anorm(2.5.1)。我经常面对这个问题,如果case类参数值为None,我不希望在SQL DB中插入/更新该参数值。例如:
case class EditableUser(
user_pk: String,
country: Option[String],
country_phone_code: Option[Int],
phonenumber: Option[String],
emailid: Option[String],
format_all: Option[String]
)
....
val eUser: EditableUser = EditableUser("PK0001", None, None, None, Some("xyz@email.com"), Some("yes"))
...
SQL"""
update #$USR SET
COUNTRY=${eUser.country},
COUNTRY_PHONE_CODE=${eUser.country_phone_code},
PHONENUMBER=${eUser.phonenumber},
EMAILID=${emailid},
FORMAT_ALL=${format_all}
where (lower(USER_PK)=lower(${eUser.user_pk}))
""".execute()
此处,当值为None时,Anorm会将“null”插入SQL DB中的相应列。相反,我想以这样的方式编写查询:Anorm跳过更新那些无,即不覆盖的值。
答案 0 :(得分:0)
您应该使用boundStatements / preparedStatement,并且在为查询设置值时,不要设置无值的列的值。
例如
SQL(
"""
select * from Country c
join CountryLanguage l on l.CountryCode = c.Code
where c.code = {countryCode};
"""
).on("countryCode" -> "FRA")
或者在你的情况下:
import play.api.db.DB
import anorm._
val stat = DB.withConnection(implicit c =>
SQL("SELECT name, email FROM user WHERE id={id}").on("id" -> 42)
)
在写你的查询的时候,你会检查你要放入的值(x->某些东西)是不是没有,如果它不好,不要放它,因此你不会更新无值的值。
答案 1 :(得分:0)
如果没有能力(或库)本身访问属性名称,那么即使在某些情况下有些笨拙,仍然有可能根据case类中存在的值动态地构建更新语句:>
case class Foo(name:String, age:Option[Int], heightCm:Option[Int])
...
def phrase(k:String,v:Option[Int]):String=if (v.isDefined) s", $k={$k}" else ""
def update(foo:Foo) : Either[String, Foo] = DB.withConnection { implicit c =>
def stmt(foo:Foo) = "update foo set "+
//-- non option fields
"name={name}" +
//-- option fields
phrase("age", foo.age) +
phrase("heightCm", foo.heightCm)
SQL(stmt(foo))
.on('name -> name, 'age -> age, 'heightCm -> heightCm)
.executeUpdate()
仍然可以在on
中指定实际提交的SQL中不存在的符号。还需要照顾其他数据类型。