2013-03-23 68 views
13

是否可以爲anorm的「on」方法動態創建一個列表?帶有Anorm和Scala Play Framework的動態SQL參數

我有一個可選輸入的表單,目前我檢查每個選項,並用定義的選項創建一個列表,並試圖將其傳遞給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] 
+1

這應該如何工作? 'whereString'看起來像什麼? – 2013-08-14 16:42:32

回答

12

重要的是您必須創建類型爲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: _* 
) 
+0

太棒了!我不知道toParameterValue函數。謝謝 – kingdamian42 2013-03-26 05:21:20

1

所以我最終只是多次呼籲。

var query = SQL("SELECT * FROM Houses WHERE " + whereString).on('school_id -> input.school) 
if(input.rooms isDefined)  query= query.on('rooms -> input.rooms.get) 
if(input.bathrooms isDefined) query= query.on('bathrooms -> input.bathrooms.get) 
if(input.houseType isDefined) query= query.on('houseType -> input.houseType.get) 
if(input.priceLow isDefined) query= query.on('priceLow -> input.priceLow.get) 
if(input.priceHigh isDefined) query= query.on('priceHigh -> input.priceHigh.get) 
if(input.utilities isDefined) query= query.on('utilities -> input.utilities.get) 
query.as(sqlToHouse *) 
1

你可以看看多值參數旁邊ANORM(即將播放2.3 /碩士)。

相關問題