一尘不染

带有Anorm和Scala Play框架的动态SQL参数

sql

是否可以为主动脉的“ on”方法动态创建列表?

我有一个带有可选输入的表单,当前我检查每个Option并使用定义的Options创建一个列表,并试图将其传递给anorm。目前,我收到此编译错误

type mismatch; found : List[java.io.Serializable] required: (Any, anorm.ParameterValue[_])

我不确定如何创建此列表。当前代码:

val onList = List(
        'school_id = input.school,
        if(input.rooms isDefined)       ('rooms -> input.rooms) else "None" ,
        if(input.bathrooms isDefined)   ('bathrooms -> input.bathrooms) else "None" ,
        if(input.houseType isDefined)   ('houseType -> input.houseType) else "None" ,
        if(input.priceLow isDefined)    ('priceLow -> input.priceLow) else "None" ,
        if(input.priceHigh isDefined)   ('priceHigh -> input.priceHigh) else "None" ,
        if(input.utilities isDefined)   ('utilities -> input.utilities) else "None" 
).filter(_!="None")
SQL("SELECT * FROM Houses WHERE " + whereString).on(onList).as(sqlToHouse *)

我尝试这样做是因为最初我认为它与

.on('rooms -> input.rooms, 'bathroom -> input.bathrooms... etc)

编辑:

现在的代码是:

val onList = Seq(
        ('school_id -> input.school),
        if(input.rooms isDefined)       ('rooms -> input.rooms.get)         else None ,
        if(input.bathrooms isDefined)   ('bathrooms -> input.bathrooms.get) else None ,
        if(input.houseType isDefined)   ('houseType -> input.houseType.get) else None ,
        if(input.priceLow isDefined)    ('priceLow -> input.priceLow.get)   else None ,
        if(input.priceHigh isDefined)   ('priceHigh -> input.priceHigh.get) else None ,
        if(input.utilities isDefined)   ('utilities -> input.utilities.get) else None 
).filter(_!=None).asInstanceOf[Seq[(Any,anorm.ParameterValue[_])]]

使用SQL命令:

SQL("SELECT * FROM Houses WHERE " + whereString).on(onList:_*).as(sqlToHouse *)

现在得到例外

[ClassCastException: java.lang.Integer cannot be cast to anorm.ParameterValue]

阅读 112

收藏
2021-05-16

共1个答案

一尘不染

重要的是您必须创建type的值ParameterValue。通常使用此toParameterValue()功能可以完成此操作。

一种方法是创建要展平的选项序列:

val onList = Seq(
  Some('school_id -> input.school),
  input.rooms.map('rooms -> _),
  input.bathrooms.map('bathrooms -> _)
).flatten

然后可以将此序列映射为正确的值:

SQL(
  "SELECT * FROM Houses WHERE " + whereString
).on(
  onList.map(v => v._1 -> toParameterValue(v._2)): _*
)

可以这样简化:

val onList = Seq(
  Some('school_id -> input.school),
  input.rooms.map('rooms -> _),
  input.bathrooms.map('bathrooms -> _)
).flatMap(_.map(v => v._1 -> toParameterValue(v._2)))

SQL(
  "SELECT * FROM Houses WHERE " + whereString
).on(
  onList: _*
)

也许最简单的解决方案是这样的:

val onList = Seq(
  Some('school_id -> toParameterValue(input.school)),
  input.rooms.map('rooms -> toParameterValue(_)),
  input.bathrooms.map('bathrooms -> toParameterValue(_))
).flatten

SQL(
  "SELECT * FROM Houses WHERE " + whereString
).on(
  onList: _*
)
2021-05-16