【发布时间】:2018-12-04 07:38:10
【问题描述】:
给定数据模型(
TableA <- TableB <- TableC
^ v
-----------------
我需要执行一个 api DELETE 操作来软删除 TableC 中的一行。如果没有更多未删除的 TableC 条目引用 TableB 中该行的父项,则此删除还必须触发对另一个服务的调用(需要来自 TableA 和 TableB 的值)。如果外部调用失败,我想回滚软删除。我想以惯用的方式完成所有这些操作(我实际上是 scala/slick 的新手),并使用事务进行回滚
根据我所阅读的内容,我需要使用 for comprehension 来组装查询,但我在让数据库操作与外部服务调用很好地融合时遇到了问题。我最初的计划是:
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 方法。然后我尝试将其分解为两部分 - 先选择,然后删除,如下所示:
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 查询返回一个 Rep[Int],它缺少一个 map 函数。此外,我的每个表(A|B|C)行映射都会引发错误,因为他们期待slick.lifted.Query[Nothing,Nothing,Seq],而他们得到slick.lifted.Query[Nothing,T,Seq]。最后,db.run 语句不想使用headOption,显然返回了不支持map 的Any
暂停
【问题讨论】:
-
httpRequestService.deleteOtherResource(tableARow.someValue, tableBRow.someValue)返回Future[_]?
标签: postgresql scala slick playback