我如何使用平滑方法在同一事务中与非DB操作一起运行相互依赖的查询

时间:2018-06-25 16:52:43

标签: postgresql scala slick playback

给出数据模型(<-表示外键依赖性)

TableA <- TableB <- TableC
   ^                 v
    -----------------

我需要执行一个API DELETE操作,以软删除TableC中的一行。如果没有更多未删除的TableC条目引用TableB中的该行的父级,则此删除操作还必须触发对另一个服务的调用(从TableA和TableB中获取值)。如果外部呼叫失败,我想回滚软删除。我想以一种惯用的方式进行所有操作(我实际上是scala / slick的新手),并使用事务进行回滚

根据我所读的内容,我需要用于理解来组装查询,但是我在使数据库操作与外部服务调用很好地融合方面遇到问题。我原来的计划是:

val select = for {
  tableCRow <- tableBDao.TableQueryC.filter(_.id === idParam)
  tableBRow <- tableBDao.TableQueryB if tableCRow.tableBForeignKey === tableBRow.id
  tableARow <- TableADao.TableQueryA if tableCRow.tableAForeignKey === tableARow.id
  count <- tableBDao.TableQueryC.filter(_.tableBForeignKey === tableBRow.id).map(_.id).countDefined
  _ <- tableBDao.softDeleteRow(idParam)
  _ <- if (count > 1) DBIO.successful(httpRequestService.deleteOtherResource(tableARow.someValue, tableBRow.someValue))
} yield ()
db.run(select.result)

但这有问题,因为我无法将Slick的Rep [T]值传递给我的httpRequestService方法。然后,我尝试将其分为两部分-首先是SELECT,然后是DELETE,如下所示:

val select = for {
  tableCRow <- tableBDao.TableQueryC.filter(_.id === idParam)
  tableBRow <- tableBDao.TableQueryB if tableCRow.tableBForeignKey === tableBRow.id
  tableARow <- TableADao.TableQueryA if tableCRow.tableAForeignKey === tableARow.id
  count <- tableBDao.TableQueryC.filter(_.tableBForeignKey === tableBRow.id).map(_.id).countDefined
} yield (tableBRow.date.formatted("yyyy-MM-DD"), tableARow.externalServiceId, count)
val result: Future[Option[(String, Long, Integer)]] = db.run(select.result.headOption)
result.map {
  case None => throw new IllegalArgumentException("exception message")
  case Some(data) =>
    val delete = for {
      _ <- tableBDao.softDeleteRow(idParam)
      _ <- if (data._3 > 1) DBIO.successful(httpRequestService.cancelSchedulerJob(data._2, data._1))
    } yield numRows
    db.run(delete.transactionally)
}

但是,尽管这实际上通过了IntelliJ IDEA检查,但由于我的count查询返回了一个缺少map函数的Rep [Int]而无法编译。另外,我的每个表(A | B | C)Row映射都引发错误,因为他们期望slick.lifted.Query[Nothing,Nothing,Seq]并且得到slick.lifted.Query[Nothing,T,Seq]。最后,db.run语句不想使用headOption,并且显然返回了不支持Any

map

半音

1 个答案:

答案 0 :(得分:0)

通过最终了解光滑如何将事物组合在一起来解决此问题。我不得不将计数从查询中拉出,并放入一个后续的groupby-> map函数中,该函数累积了我要计数的事物列表,然后对它们进行了计数,而不是将其作为查询的一部分进行计数。这也解决了所有其他问题,因为count查询排除了其他所有内容的预期返回类型。

基本上,解决方案看起来像(thing1用于联接):

  { <Link  to="/user-login"  ><Button onClick={this.logout} style={{ color: '#036cd2',verticalAlign:'middle', borderColor: '#ffffff', backgroundColor: '#ffffff', border: 0, visibility: this.props.colBtn,marginRight:5 }}  shape={'circle'}><Icon type="poweroff" /></Button></Link> }