在 Slick 3 中以事务方式使用
Posted
技术标签:
【中文标题】在 Slick 3 中以事务方式使用【英文标题】:Using transactionally in Slick 3 【发布时间】:2016-05-19 00:51:22 【问题描述】:通常您会在一个事务中运行两个或多个语句。但在我能找到的在 Slick 3 中使用 transactionally
的所有示例中,当我通常在循环中使用 for
时,有一个 for comprehension 可以对这些语句进行分组。
这可行(从事务中的两个表中删除):
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
吗?有没有另一种方法可以在一个事务中运行两个或多个语句?
【问题讨论】:
【参考方案1】:您可以在每个DBIOAction
上使用transactionally
,而不仅仅是那些 for 理解的结果。例如,您可以将transactionally
与DBIO.seq
方法结合使用,该方法采用一系列操作并按顺序运行它们:
val firstAction = table1.filter(_.id === id1).delete
val secondAction = table2.filter(_.id === id2).delete
val combinedAction = DBIO.seq(
firstAction,
secondAction
).transactionally
【讨论】:
【参考方案2】:对于您的情况,for/yield
并不是获得所需内容的唯一方法。但是您必须将其替换为等效表示。
对于 flatMap
s 和 map
的组合,for 理解是 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 推导式,因为它更简洁、更易于理解且非常易于扩展。
让我们看一个事务中包含 4 个语句的示例,看看它的外观:
这将是一个 for 理解:
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/map
s:
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)
【讨论】:
您的示例似乎不正确。每个map
调用实际上应该是flatMap
调用,否则map 中的最后一个动作不会被执行,它只会创建一个动作并丢弃它。以上是关于在 Slick 3 中以事务方式使用的主要内容,如果未能解决你的问题,请参考以下文章