0Pricing
Scala for Backend Engineering & Functional Programming · 课时

运行查询

将行读取为样例类。

运行查询 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

sql 插值器

Doobie 的 sql 字符串插值器是查询的核心。它会解析您的 SQL,并将嵌入的 Scala 值转换为安全的绑定参数。

插值后的值会成为 JDBC 的 ? 占位符,因此不会发生 SQL 注入,也不需要手动连接 PreparedStatement。

import doobie.implicits._

val minAge = 18
val frag = sql"select name from users where age >= $minAge"

从 Fragment 到查询

sql"..."表达式是一个Fragment。要将其作为读取操作执行,您需要调用.query[A],并选择行类型A。

Doobie 使用Read[A]类型类将结果列映射到A,支持基本类型、元组和样例类。

case class User(name: String, age: Int)

val q: Query0[User] =
  sql"select name, age from users".query[User]

unique、option 和 to

Query0[A]提供了不同的累加器。.unique要求恰好一行,.option要求零行或一行,而.to[List]会收集所有行。

每个累加器都会返回一个之后通过.transact执行的ConnectionIO。

val one: ConnectionIO[User] = q.unique
val maybe: ConnectionIO[Option[User]] = q.option
val all: ConnectionIO[List[User]] = q.to[List]

将行映射到样例类

当样例类的每个字段都有列映射时,Doobie 会自动为其派生Read实例。列的顺序必须与选择列表一致。

这样,您无需编写繁琐的行解析代码,就可以直接将查询结果选择为丰富的领域类型。

case class Account(id: Long, email: String, active: Boolean)

val accounts =
  sql"select id, email, active from accounts"
    .query[Account].to[Vector]

参数化查询

每个插值的 Scala 值都会使用其Put实例绑定为参数。您可以插入任意数量的值,也可以将它们放在不同位置。

由于这些值是绑定的,而不是通过拼接生成的,因此类型会得到检查,也不可能发生注入。

def findByEmail(email: String): ConnectionIO[Option[Account]] =
  sql"select id, email, active from accounts where email = $email"
    .query[Account].option

流式处理大型结果

对于大型结果集,请使用.stream获取 fs2Stream[ConnectionIO, A]。行会通过服务器端游标惰性地读取,从而将内存占用控制在有限范围内。

将它与 fs2 组合器结合使用,即可增量处理数百万行。

import fs2.Stream

val s: Stream[ConnectionIO, Account] =
  sql"select id, email, active from accounts"
    .query[Account].stream

控制提取数量

在某些驱动程序中,默认的游标提取数量可能会一次性加载全部数据。.streamWithChunkSize(n)会设置 JDBC 提取数量,使游标每次往返提取 n 行。

调整该值可以在往返次数和内存占用之间取得平衡。

val s =
  sql"select id, email, active from accounts"
    .query[Account]
    .streamWithChunkSize(512)

可选列与可空性

可空列会映射到行类型中的Option[A]。如果某列可能为 NULL,您必须将其读取为 Option,否则 Doobie 会在遇到空值时抛出错误。

这样,边界处的可空性就变得明确且类型安全。

case class Person(id: Long, nickname: Option[String])

val ps =
  sql"select id, nickname from people".query[Person].to[List]

使用 Fragments 构建 SQL

Fragment值可以通过++进行组合,让您在保持参数绑定的同时,从多个片段组装查询。

fr插值器会构建一个末尾带空格的片段,这对于拼接各个子句非常方便。

val base = fr"select id, email, active from accounts"
val where = fr"where active = $${true}"
val q = (base ++ where).query[Account]

动态 WHERE 子句

Doobie 的Fragments辅助工具可以构建条件子句。Fragments.whereAndOpt会组合可选过滤条件,只生成实际存在的条件。

这是构建安全动态搜索查询的惯用方式。

import doobie.util.fragments._

val emailOpt: Option[String] = Some("a@b.com")
val filter = whereAndOpt(emailOpt.map(e => fr"email = $e"))
val q = (fr"select id, email, active from accounts" ++ filter)

在构建时检查查询

Doobie 的check分析会针对数据库模式运行查询,以验证列的类型和数量是否与您的 Scala 类型匹配。

在测试中使用它,可以在模式变更影响生产环境之前发现问题。

import doobie.scalatest._

// inside a spec mixing in IOChecker
check(sql"select id, email, active from accounts".query[Account])

快速检查

请选择合适的累加器。

回顾

sql插值器会构建参数化的Fragment;.query[A]会将其转换为通过Read[A]映射的Query0[A]。

请选择.unique、.option、.to[List]或.stream来累加行。使用Fragments构建动态子句,并使用check针对模式进行验证。

常见问题解答

「运行查询」课时是免费的吗?

是的 — 「运行查询」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

「运行查询」这节课中我会学到什么?

将行读取为样例类。 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「运行查询」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?

能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用事务处理器连接
  2. 运行查询
  3. 插入与更新
  4. 组合事务
← 返回 Scala for Backend Engineering & Functional Programming