2012-12-07 27 views
17

如何Slick轉換代碼,如:Scala Slick如何將Scala代碼轉換爲JDBC?

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) 

進入JDBC?

它使用Scala虛擬化嗎?它是否使用其他方法?

回答

31

Slick的穩定的API通過它所稱的實現了這一點,取消了嵌入。你的例子顯然是使用穩定的API(因爲你使用===來實現平等,而不是==)。

Slick(又稱Scala)的美妙之處在於 - 不需要使用宏或Scala-虛擬化就可以實現這一點。 (旁註:油滑的實驗API不使用宏 - 這將允許您使用==,而不是===is)使用

的轉換爲SQL實現:

  1. Scala的for理解語法,將其翻譯爲方法調用。在油滑定義 表是單子 - 它們具有魔foreachmapflatMap,和 filter方法,其允許它們在for表達「環」,而Scala的 它們轉換爲方法調用(作爲正確地示出代碼 由the other answer by @emil-ivanov提供)。

    與常規Scala集合,所述for爲嵌套 方法語法糖調用flatMap/mapfilter; 不像定期收集, 光滑Table對象的map版本和filter回報表示 查詢,構建它與每一個過濾條件(if)沿或加入 (如s <- Suppliers if s.id is c.supID

    所以類型q2不是您常用的集合(因爲在Scala中用於理解 通常用於返回),而是查詢的表示形式。 (正如Scala Option Monadfor推導儘管 不是一個「集合」(在方式ListMap是)的作品)

    你可以看到下面的查詢與q2.selectStatement

  2. Scala的隱式起重 - c.price不是Int而是 一列值的表示 - 這樣的表達c.price < 9.0變得c.price.<(Const(9.0)) (一個Int被提升到所期望的類型),以及<是一剛一代表c.priceColumn的 類的方法。該<方法 沒有做什麼<平常不同(以純Int S的情況下) - 這只是返回 對應於price < 9的SQL AST變成的表示的 部分被生成並被髮送關閉以JDBC到SQL執行。

在細節方面還有很多事情要做,但我認爲查詢monad和隱式提升是主要成分。

+0

真的很棒的文章。隱含的提升很聰明 –

14

在斯卡拉for「循環」實際上並不是一種特殊的語言結構,而是語法糖。你的第一個例子

val q2 = for { 
    c <- Coffees if c.price < 9.0 
    s <- Suppliers if s.id === c.supID 
} yield (c.name, s.name) 

轉化爲東西的線路:

val q2 = Coffees.withFilter(_.price < 9.0).flatMap(c => 
    Suppliers.withFilter(_.id === c.supID).map(s => 
     (c.name, s.name) 
    ) 
) 

現在,flatMapmapwithFilter(和foreach)實際上並不過濾收集,而是收集什麼hapening在一個AST(抽象語法樹),然後將其處理爲Slick以轉換爲SQL。

此外,c.pricec.supID實際上油滑column S,其<>===(等)方法不返回布爾,但收集的比較,以及,這 後來被流傳下來轉換爲SQL。

This is a talk由創造者,其中大部分描述(正確)。

相關問題