Scala Slick如何将Scala代码转换为JDBC?

时间:2012-12-07 07:03:51

标签: scala slick

Slick如何翻译代码,如:

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 Virtualized?它是否使用其他方法?

2 个答案:

答案 0 :(得分:31)

Slick的稳定API 通过它所谓的提升嵌入来实现这一目标。您的示例显然正在使用稳定的API(因为您使用===表示相等而不是==)。

Slick(反过来Scala)的美妙之处在于 - 这可以在不使用宏或Scala-Virtualized的情况下实现。 (附注:Slick的实验性API 确实使用了宏 - 这样您就可以使用==代替===is

使用以下方法实现对SQL的转换:

  1. Scala的for理解语法,转换为方法调用。 Slick中定义的表格是 Monads - 它们具有魔力foreachmapflatMap,和 filter方法允许它们在Scala中以for'循环'表示 将它们转换为方法调用(如代码中正确说明的那样) 由the other answer by @emil-ivanov提供。

    与常规Scala集合一样,for是嵌套的语法糖 方法调用flatMap / mapfilter; 常规集合不同, Tablemap的Slick filter个对象版本返回表示 查询,与每个过滤条件(if)或连接一起构建它 (如s <- Suppliers if s.id is c.supID

    所以q2类型不是你常用的集合(作为对Scala的理解) 通常用于返回),而是查询的表示。 (尽管Scala Option Monad也适用于for理解 不是“集合”(以ListMap的方式))

    您可以使用q2.selectStatement查看基础查询。

  2. Scala的隐式解除 - c.price不是Int,而是代表 列值 - 因此表达式c.price < 9.0变为c.price.<(Const(9.0))Int被提升到所需类型),而<只是一种方法 代表c.price的类,Column<方法 不执行<通常做的事情(在普通Int s的情况下) - 它只是返回 与price < 9对应的SQL AST的表示形式 生成并发送给JDBC执行的SQL。

  3. 在细节方面还有很多其他事情,但我认为查询monad和隐含的提升是主要成分。

答案 1 :(得分:14)

在Scala中,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)实际上并未对集合进行过滤,而是收集AST中的所有内容(抽象语法树) ),然后处理到Slick转换为SQL。

此外,c.pricec.supID实际上是Slick column,其<>===(等等)方法不要返回bool,但也要收集比较 稍后传递下来转换为SQL。

创作者

This is a talk,其中大部分内容都是(正确地)描述的。