在光滑的查询中删除多个表中的行

时间:2017-02-01 23:25:28

标签: scala slick slick-3.0

我用谷歌搜索并找到了这个帖子Slick 3.0: Delete rows from multiple tables in a transaction但是解决方案说这不是一个好的解决方案。

我正在使用我的代码

删除多个表中的行
val deleteB = for {
  aId <- TableA.filter(a => a.id === param).map(_.id)
  bId <- TableB.filter(_.aId === aId)
} yield bId

val deleteC = for {
  aId <- TableA.filter(a => a.id === param).map(_.id)
  cId <- TableC.filter(_.aId === aId)
} yield cId

val deleteA = TableA.filter(a.Id === param)

val query = (deleteC.delete andThen deleteB.delete andThen deleteA.delete).transactionally
db.run(query)

但我想知道是否有更好的方式来写这个。

上述方法的问题在于我想返回从TableA中删除的行数,而不是从子表TableB和TableC中删除的行的总和。

此外,在运行时它抱怨在删除查询中加入。

2 个答案:

答案 0 :(得分:2)

以下将解决加入警告/错误。

val deleteB = TableB.filter(_.aid in TableA.filter(a => a.id === id).map(_.id))

val deleteC = TableC.filter(_.aid in TableA.filter(a => a.id === id).map(_.id))

val deleteA = TableA.filter(_.id === id)

db.run((deleteB.delete andThen deleteC.delete andThen deleteA.delete).transactionally)

由于您使用andThen来链接您的操作,因此组合操作将始终返回上述here的最后一个操作的受影响行数。因此,返回的数字始终是从deleteA操作中删除的行,因为这是andThen链中的最后一个操作。

<强> andThen

  

在此之后运行另一个操作   动作,如果成功完成,并返回结果   第二个动作。如果两个操作中的任何一个失败,则生成   行动也失败了。

答案 1 :(得分:2)

我认为你也可以这样做 -

 def buildTransactionQuery = {
    for {
      deleteA <- TableA.filter(a.Id === param)
      deleteB  <- TableB.filter(_.aId === deleteA.map(_.id))
      deleteC  <- TableC.filter(_.aId === deleteA.map(_.id))

      deleteAAction = deleteA.delete
      deleteBAction = deleteB.delete
      deleteCAction = deleteC.delete
      res = (deleteAAction, deleteBAction, deleteCAction)
    } yield res
  }

  def executeTransactionQuery = {
    val transactionQuery = for {
      queries <- buildTransactionQuery
      action = DBIOAction.seq(queries._3, queries._2, queries._1)
    } yield action
    transactionQuery.flatMap(action => db.run(action.transactionally).transform(s => true, t => {
      logger.error(t.getMessage)
      t
    }))
  }