将 DBIO 值转换为自定义大小写 Class

Transform DBIO Value to Custom Case Class

我有一个 DBIO[Seq[tuple]],我想将它映射到 DBIO[Seq[customCaseClass]]

我知道我可以对 db.run() 结果进行转换,例如:customCaseClass.tupled(row) (see this answer)。但是,我有兴趣在不同的函数中组合 DBIO return 值。

您可以在三个地方执行此操作:在 Query 级别、DBIO 级别和(如您所述,并已拒绝)在 Future 级别。

查询

在查询级别,转换将作为在 Slick 自己的执行上下文中执行查询的一部分发生。

看起来像这样:

// Given some query that returns a tuple...
val tupleQ: Query[(Rep[String],Rep[String]), (String,String), Seq] =
   table.map{ row => (row.column1, row.column2) }

// ...which we'd like to project into this:
case class SomeCaseClass(v1: String, v2: String)

// ...we can use the mapTo macro to generate the conversion:
val ccQ: Query[Rep[SomeCaseClass], SomeCaseClass, Seq] =
   tupleQ.map{ _.mapTo[SomeCaseClass] }

如果这就是您所做的全部,那么默认投影 (def * ...) 可能就是这样做的地方。

如果您需要对转换逻辑进行更多控制,可以使用较低级别的 <> 代替 mapToSection 5.2 of Essential Slick 对此提供了更多详细信息。

DBIO

问题专门针对 DBIO。那里的转换将在您自己的执行上下文中 运行 。

看起来像这样:

// Given a DBIO that returns a tuple...
val tupleD: DBIO[Seq[(String,String)]] =
  table.map(row => (row.column1, row.column2)).result

// ... we can use any of the DBIO combinators to convert it, such as map:
val ccD: DBIO[Seq[SomeCaseClass]] =
  dQ.map{ pairs => pairs.map{ case (a, b) => SomeCaseClass(a,b) } }

(...或如您所述 dQ.map(pairs => pairs.map(SomeCaseClass.tupled)))。

您在此级别获得的两大好处是:

  1. 您可以访问这些值,例如 (a,b),因此可以决定要对这些值执行的操作。
  2. 成为行动的一部分意味着您可以参与交易。

Chapter 4 of Essential Slick lists out many of the DBIO combinators. The Slick Manual 也描述了组合器。

未来

最后一个位置在 Future 中,它看起来非常像 DBIO 版本,但在 db.run 之后(如您所见)。