使用 Slick 3.0 在同一事务中进行多次插入
Posted
技术标签:
【中文标题】使用 Slick 3.0 在同一事务中进行多次插入【英文标题】:Multiple inserts in same transaction with Slick 3.0 【发布时间】:2015-07-07 10:31:01 【问题描述】:我正在使用 slick 2.1.0 将我的 Play Framework 应用程序升级到 play-slick 1.0.0(包括 slick 3.0.0)。
我在理解如何处理交易时遇到了一些问题。
假设我有以下代码:
db.withTransaction implicit session =>
for (id <- ids) yield someTable.insert(SomeObject(id))
如何在 slick 3 中做到这一点?我希望将所有对象插入一个事务中。如果一个对象插入失败,则不应插入任何对象。
【问题讨论】:
【参考方案1】:根据documentation,您可以在db-action 上使用.transactionally
:
val a = (for
ns <- coffees.filter(_.name.startsWith("ESPRESSO")).map(_.name).result
_ <- DBIO.seq(ns.map(n => coffees.filter(_.name === n).delete): _*)
yield ()).transactionally
val f: Future[Unit] = db.run(a)
对于您提供的代码,这会产生以下示例:
val a = (for (id <- ids)
someTable.insert(SomeObject(id))
yield ()).transactionally
val f: Future[Unit] = db.run(a)
【讨论】:
那行不通。似乎函数insert
不再存在。我尝试将其替换为+=
,但这也不起作用。
玩了一会儿后,我想到了这个:val toInsert = for (id <- ids) yield SomeObject(id)
val insertActions = DBIO.seq(someTable ++= toInsert.toSeq).transactionally
val f: Future[Unit] = db.run(insertActions)
不确定这是否是最好的方法?【参考方案2】:
我有一个稍微不同的场景,我必须在同一个事务中更新两个表,下面的代码似乎是实现这一点的最优雅的方式:
val c: DBIOAction[(Int, Int), NoStream, Effect.Write with Effect.Write] = for
i1 <- (tbl1 += record1)
i2 <- (tbl2 += record2)
yield
(i1,i2)
val f = db run c.transactionally
看到这里,突然觉得这有点像scala Future的api,所以肯定有sequence方法,而且确实有:
val actions = Seq((tbl1 += record1), (tbl2 += record2))
val dbActions: DBIOAction[Seq[Int], NoStream, Effect.Write with Effect.Transactional]
= DBIOAction.sequence(actions).transactionally
val f = db run dbActions
在原始用例中,您可以简单地用您的理解构建动作。
【讨论】:
以上是关于使用 Slick 3.0 在同一事务中进行多次插入的主要内容,如果未能解决你的问题,请参考以下文章