在 Slick 3 中以事务方式使用

Using transactionally in Slick 3

通常您会 运行 一个事务中的两个或多个语句。但是在我能找到的所有关于在 Slick 3 中使用 transactionally 的示例中,当我通常在循环中使用 for 时,有一个用于对这些语句进行分组的理解。

这有效(从事务中的两个表中删除):

   val action = db.run((for {
      _ <- table1.filter(_.id1 === id).delete
      _ <- table2.filter(_.id2=== id).delete
    } yield ()).transactionally)
    val result = Await.result(action, Duration.Inf)

但是 for/yield 是必需的吗?是否有替代方法 运行 交易中的两个或多个语句?

对于您的情况,for/yield 并不是获得所需内容的唯一途径。但是你必须用它来代替等效的表示。 对于 flatMapmap 的组合,for comprehension 是 syntactic sugar。我们需要使用它们,因为我们正在使用单子组合来聚合 BDIOAction 中的所有操作。 所以你也可以写成:

val action = db.run(
  table1.filter(_.id1 === id).delete.map ( _ =>
    table2.filter(_.id2=== id).delete
  ).transactionally
)
val result = Await.result(action, Duration.Inf)

通常使用 for comprehension,因为它更简洁、更容易理解并且非常容易扩展。

让我们看一个事务中包含 4 个语句的示例,看看它的外观:

  • 这将有一个理解:

    val action = db.run((for {
      _ <- table1.filter(_.id1 === id).delete
      _ <- table2.filter(_.id2=== id).delete
      _ <- table3.filter(_.id3=== id).delete
      _ <- table4.filter(_.id4=== id).delete
    } yield ()).transactionally)
    val result = Await.result(action, Duration.Inf)
    
  • 这将与 flatMap/maps:

    val action = db.run(
      table1.filter(_.id1 === id).delete.flatMap ( _ =>
        table2.filter(_.id2 === id).delete.flatMap ( _ =>
          table3.filter(_.id3 === id).delete.map ( _ =>
            table4.filter(_.id4=== id).delete
          )
        )
      ).transactionally
    )
    val result = Await.result(action, Duration.Inf)
    

您可以在每个 DBIOAction 上使用 transactionally,而不仅仅是那些 for 理解的结果。例如,您可以将 transactionallyDBIO.seq 方法结合使用,该方法采用一系列操作并按顺序运行它们:

val firstAction = table1.filter(_.id === id1).delete
val secondAction = table2.filter(_.id === id2).delete

val combinedAction = DBIO.seq(
  firstAction,
  secondAction
).transactionally