scala slick 如何确定要在此查询中更新哪些行

How does scala slick determin which rows to update in this query

有人问我 scala slick 如何根据这段代码确定哪些行需要更新

      def updateFromLegacy(criteria: CertificateGenerationState, fieldA: CertificateGenerationState, fieldB: Option[CertificateNotification]) = {
        val a: Query[CertificateStatuses, CertificateStatus, Seq] = CertificateStatuses.table.filter(status => status.certificateState === criteria)
        val b: Query[(Column[CertificateGenerationState], Column[Option[CertificateNotification]]), (CertificateGenerationState, Option[CertificateNotification]), Seq] = a.map(statusToUpdate => (statusToUpdate.certificateState, statusToUpdate.notification))
        val c: (CertificateGenerationState, Option[CertificateNotification]) = (fieldA, fieldB)
        b.update(c)
      }

以上代码是(如我所见)

然后查询用于查找需要应用元组的行。

背景

我想知道 slick 是否跟踪要更新的行的 ID。

我想了解什么

好的 - 我稍微重新格式化了您的代码以便在此处更容易看到它并将其分成块。让我们一一过一遍:

    val a: Query[CertificateStatuses, CertificateStatus, Seq] = 
        CertificateStatuses.table
            .filter(status => status.certificateState === criteria)

以上是一个大致翻译成以下内容的查询:

SELECT *  // Slick would list here all your columns but it's essiantially same thing
FROM certificate_statuses
WHERE certificate_state = $criteria

下面映射了这个查询,即应用了一个 SQL 投影:

    val b: Query[
        (Column[CertificateGenerationState], Column[Option[CertificateNotification]]), 
        (CertificateGenerationState, Option[CertificateNotification]), 
        Seq] = a.map(statusToUpdate =>
            (statusToUpdate.certificateState, statusToUpdate.notification))

因此,您将得到的不是 *

SELECT certificate_status, notification
FROM certificate_statuses
WHERE certificate_state = $criteria

最后一部分是重用这个构造的查询来执行更新:

    val c: (CertificateGenerationState, Option[CertificateNotification]) = 
        (fieldA, fieldB)

    b.update(c)

转换为:

UPDATE certificate_statuses
SET certificate_status = $fieldA, notification = $fieldB
WHERE certificate_state = $criteria

我知道最后一步可能没有其他步骤那么简单,但这基本上就是您使用 Slick 进行更新的方式(here - 虽然它是单子版本)。

关于您的问题:

What is happening behind the covers?

这实际上超出了我的专业领域。话虽这么说,这是一段相对简单的代码,我想更新转换可能会引起一些兴趣。我在这个答案的末尾为您提供了 link 相关的 Slick 来源。

What is Seq in "val a:Query[CertificateStatuses, CertificateStatus, Seq]"

是collection类型。查询指定 3 个类型参数:

  • mixed type - table(或列 - Rep

  • 的流畅表示
  • unpacked type - 执行查询后得到的类型

  • collection type - collection 类型以上 unpacked type 已作为查询结果为您放置。

举个例子:

  • CertificateStatuses - 这是你的 Slick table 定义

  • CertificateStatus这是你的情况class

  • Seq - 这就是检索结果的方式(基本上是 Seq[CertificateStatus]

我在这里解释了它:http://slides.com/pdolega/slick-101#/47(以及接下来的 3 张左右的幻灯片)

Can someone maybe point out the slick source where the moving parts are located?

我认为这部分可能很有趣 - 它显示了如何在更新语句中转换查询:https://github.com/slick/slick/blob/51e14f2756ed29b8c92a24b0ae24f2acd0b85c6f/slick/src/main/scala/slick/jdbc/JdbcActionComponent.scala#L320

也许还值得强调一下:

I wonder were slick keeps track of the Ids of the rows to update.

它没有。 查看生成的 SQLs。您可以通过将以下配置添加到您的日志记录中来查看它们(但您在这个答案中也有它们):

<logger name="slick.jdbc.JdbcBackend.statement" level="DEBUG" />

(我假设上面 logback)。