2013-03-23 16 views
13

Ist es möglich, dynamisch eine Liste für die "on" -Methode von anorm zu erstellen?Dynamische SQL-Parameter mit Anorm und Scala Play Framework

Ich habe ein Formular mit optionalen Eingaben und zur Zeit überprüfe ich jede Option und erstelle eine Liste mit den definierten Optionen und versuche dies an anorm weiterzuleiten. Zur Zeit bekomme ich diese Kompilierung Fehler

Ich bin mir nicht sicher, wie ich über das Erstellen dieser Liste gehen würde. Aktueller Code:

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

Ich habe versucht das zu tun, weil anfangs dachte ich, es wäre das gleiche wie

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

EDIT:

-Code ist jetzt:

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

mit SQL-Befehl:

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

nun die Ausnahme

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

Wie soll das funktionieren? Wie sieht 'whereString' aus? –

Antwort

12

Wichtig ist, dass Sie Werte vom Typ ParameterValue erstellen müssen. Dies geschieht normalerweise mit der toParameterValue() Funktion.

Eine Möglichkeit wäre, eine Folge von Optionen zu erstellen, die Sie glätten:

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

Diese Sequenz kann dann korrigieren Werte abgebildet werden:

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

Dies kann wie vereinfacht werden dies:

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

Oder vielleicht die einfachste Lösung wäre dies:

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

Das ist großartig! Ich wusste nichts über die Funktion toParameterValue. Vielen Dank – kingdamian42

1

Also habe ich mehrmals aufforderte gerade gelandet ist.

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

Sie können bei Mehrwert-Parameter einen Blick neben Anorm (Wiedergabe kommenden 2.3/Master).