Comment Scala Slick traduit-il le code Scala en JDBC?
Comment Slick traduire le code tel que:
val q2 = for {
c <- Coffees if c.price < 9.0
s <- Suppliers if s.id === c.supID
} yield (c.name, s.name)
for(t <- q2) println(" " + t._1 + " supplied by " + t._2)
dans JDBC?
utilise-t-il Scala virtualisé? Faut-il utiliser une autre méthode?
2 réponses
Slick API stable réalise ce par ce qu'il appelle levé l'incorporation de . Votre exemple utilise clairement L'API stable (comme vous utilisez ===
pour l'égalité et non ==
).
la beauté de Slick (et à son tour Scala) est que - ce beaucoup est réalisé sans utiliser les macros ou Scala-virtualisé. (Note de Côté: Slick expérimental API fait de l'utilisation de macros et permettez-les d'être exprimés en for
'boucles' tandis que Scala
traduit pour les appels de méthode (comme correctement illustré dans le code
fourni par l'autre réponse de @emil-ivanov ).
comme pour les collections régulières de Scala, le for
est du sucre syntaxique pour emboîter
appels de méthode à flatMap
/ map
et filter
; contrairement à collections régulières,
les versions Slick Table
des objets map
et filter
retour représentations
d'une requête, la construire avec chaque condition de filtre ( if
) ou joindre
(comme dans s <- Suppliers if s.id is c.supID
)
ainsi le type de q2
n'est pas votre collection habituelle (comme pour la compréhension en Scala
est généralement utilisé pour le retour), mais plutôt une représentation d'une requête.
(Tout comme L'Option Scala Monad fonctionne aussi avec for
malgré les interprétations de la
n'étant pas une "collection" (comme List
ou Map
est)
Vous pouvez voir la requête sous-jacente avec q2.selectStatement
.
l'implicite de Scala lifting - c.price
n'est pas une Int
mais plutôt une représentation de
une valeur de colonne - ainsi l'expression c.price < 9.0
devient c.price.<(Const(9.0))
(un Int
est soulevé au type désiré), et <
est une méthode juste de la
classe qui représente c.price
, une Column
. La méthode <
ne fait pas ce que <
fait habituellement (dans le cas de "Uni Int
s) - il retourne simplement
une représentation de la SQL AST correspondant à price < 9
qui fait partie
le SQL qui est généré et envoyé à JDBC pour être exécuté.
il y a beaucoup d'autres choses qui se passent, en termes de détails, mais je pense que le interrogation monad et le levage implicite sont les ingrédients principaux.
en Scala, la" boucle "151920920 n'est pas en fait une construction linguistique particulière, mais plutôt un sucre syntaxique. Votre premier exemple
val q2 = for {
c <- Coffees if c.price < 9.0
s <- Suppliers if s.id === c.supID
} yield (c.name, s.name)
se traduit par quelque chose dans les lignes de:
val q2 = Coffees.withFilter(_.price < 9.0).flatMap(c =>
Suppliers.withFilter(_.id === c.supID).map(s =>
(c.name, s.name)
)
)
maintenant, le flatMap
, map
, withFilter
(et foreach
) ne filtrent pas réellement la collection, mais recueillent plutôt ce qui est hapening dans un AST (Arbre de syntaxe abstraite), qui est ensuite manipulé à Slick pour traduire en SQL.
aussi, c.price
, c.supID
sont en fait lisse column
s, dont <
, >
, ===
(et ainsi de suite) les méthodes ne renvoient pas bool, mais recueillent la comparaison ainsi, qui
est ensuite transmis pour être converti en SQL.
C'est un talk par les créateurs, où la plupart de ce qui est décrit (correctement).