2013-03-23 17 views
13

Czy możliwe jest dynamiczne tworzenie listy dla metody anorm? On?Dynamiczne parametry SQL z Anorm i Scala Play Framework

Mam formularz z opcjonalnymi wejściami i obecnie sprawdzam każdą opcję i tworzę listę z określonymi opcjami i próbuję przekazać to do anorm. Obecnie dostaję ten błąd kompilacji

Nie jestem pewien, w jaki sposób chciałbym utworzyć tę listę. Aktualny kod:

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 *) 

Próbowałem to zrobić, ponieważ początkowo myślałem, że to będzie taka sama jak

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

EDIT:

Code jest teraz:

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[_])]] 

przy użyciu polecenia SQL:

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

Teraz coraz wyjątek

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

Jak to ma działać? Jak wygląda 'whereString'? –

Odpowiedz

12

Ważne jest, aby utworzyć wartości typu ParameterValue. Zwykle wykonuje się to za pomocą funkcji toParameterValue().

Jednym ze sposobów byłoby utworzyć sekwencję opcje, które spłaszczyć:

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

Sekwencja ta może być odwzorowany w celu skorygowania wartości:

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

ten można uprościć jak to:

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: _* 
) 

A może najprostszym rozwiązaniem byłoby to:

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

To świetnie! Nie wiedziałem o funkcji toParameterValue. Dzięki – kingdamian42

1

więc skończyło się tylko wzywając wielokrotnie.

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

Można spojrzeć na wielowartościowych parametr jest następny Anorm (pochodzących Zagraj 2,3/Master).

Powiązane problemy