2015-09-19 10 views
8

ho una definizione Slick 3.0 tabella simile al seguente:colonne quotazione in un tavolo Slick

case class Simple(a: String, b: Int, c: Option[String]) 

trait Tables { this: JdbcDriver => 
    import api._ 

    class Simples(tag: Tag) extends Table[Simple](tag, "simples") { 
    def a = column[String]("a") 
    def b = column[Int]("b") 
    def c = column[Option[String]]("c") 

    def * = (a, b, c) <> (Simple.tupled, Simple.unapply) 
    } 

    lazy val simples = TableQuery[Simples] 

} 

object DB extends Tables with MyJdbcDriver 

Vorrei essere in grado di fare 2 cose:

  1. ottenere un elenco dei nome colonna come Seq[String]
  2. Per un'istanza di Simple, generare un Seq[String] che corrisponderebbe a come i dati verrebbero inseriti nel database utilizzando una query non elaborata (ad esempio Simple("hello", 1, None) diventa Seq("'hello'", "1", "NULL"))

Quale sarebbe il modo migliore per farlo utilizzando la definizione della tabella Slick?

risposta

6
  • Innanzitutto non è possibile ingannare Slick e cambiare l'ordine sul lato sinistro della <> operatore nel metodo * senza cambiare l'ordine dei valori nel Simple, il tipo di riga di Simples, cioè quello che Ben Presupposto non è possibile. Il tipo di restituzione ProvenShape del metodo di proiezione * garantisce che sia disponibile un Shape per la conversione tra il tipo basato su Column in * e sul lato client e se si scrive def * = (c, b, a) <> Simple.tupled, Simple.unapply) con Semplice definito come case class Simple(a: String, b: Int, c: Option[String]), Slick si lamenterà di un errore " Nessuna forma corrispondente trovata. La chiazza di petrolio non sa come mappare i tipi dati ... ". Ergo, puoi scorrere tutti gli elementi di un'istanza di Simple con il suo productIterator.
  • In secondo luogo, è già presente la definizione della tabella Simples nel codice e l'esecuzione di query sui metatable per ottenere che le stesse informazioni già presenti non siano sensibili. È possibile ottenere tutti i nomi delle colonne con una linea singola simples.baseTableRow.create_*.map(_.name). Si noti che la proiezione * della tabella definisce anche le colonne generate quando si crea lo schema della tabella. Quindi le colonne non menzionate nella proiezione non vengono create e la dichiarazione di cui sopra è garantita per restituire esattamente ciò che ti serve e non far cadere nulla.

Per ricapitolare brevemente:

  1. per ottenere un elenco dei nomi delle colonne della tabella Semplici come Seq[String] uso simples.baseTableRow.create_*.map(_.name).toSeq
  2. Per generare un Seq[String] che corrisponderebbe al modo in cui i dati sarebbe inserito nel database utilizzando una query non elaborata per aSimple, un'istanza di Simple utilizza aSimple.productIterator.toSeq
+0

Grazie per la comprensione di 'simples.baseTableRow.create _ *. Map (_. Name) .toSeq'. È bene sapere che ritorna nell'ordine della proiezione. Penso che questo risponda completamente alla domanda (e l'ho scelta come risposta). Tuttavia, non penso che 'productIterator' funzioni se ho definito il mapping' <> 'utilizzando le funzioni personalizzate. Idealmente, vorrei essere in grado di mappare direttamente per convertire 'aSimple' in un' Seq [String] ' –

1

Per ottenere i nomi delle colonne, provate questo:

db.run(for { 
     metaTables <- slick.jdbc.meta.MTable.getTables("simples") 
     columns <- metaTables.head.getColumns 
     } yield columns.map {_.name}) foreach println 

questo stampa

Vector(a, b, c) 

e per i valori caso classe, è possibile utilizzare productIterator:

Simple("hello", 1, None).productIterator.toVector 

è

Vector(hello, 1, None) 

È ancora necessario eseguire il mapping dei valori e garantire che l'ordine delle colonne nella tabella e i valori nella classe case siano uguali.

+1

Mi piace usare i metadati (non sapevo che fosse in Slick). Idealmente, vorrei usare la mappatura delle tabelle Slick per mantenere l'ordine lo stesso. Sai di qualsiasi modo per farlo? –

+0

L'ordine è l'ordine di definizione, non è vero? – Edmondo1984

+0

@ Edmondo1984 L'ordine per 'productIterator' è l'ordine di definizione, ma penso che quello che intende è che non c'è alcuna garanzia che sarà uguale all'ordine di colonne sulla tabella (ad esempio se l'ultima riga della definizione di classe di 'Simples' erano' def * = (c, b, a) <> (Simple.tupled, Simple.unapply) ') nel qual caso non si poteva usare banalmente il nome della colonna da' getColumns' con i valori di ' productIterator'. –

Problemi correlati