gpt4 book ai didi

postgresql - 如何使用 slick 在同一事务中运行相互依赖的查询以及非数据库操作

转载 作者:行者123 更新时间:2023-11-29 13:44:07 27 4
gpt4 key购买 nike

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

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

我需要执行一个 api DELETE 操作来软删除 TableC 中的一行。如果在 TableB 中没有更多未删除的 TableC 条目引用该行的父项,则此删除还必须触发对另一个服务的调用(需要来自 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 查询返回一个缺少 map 函数的 Rep[Int]。此外,我的每个表 (A|B|C) 行映射都会引发错误,因为它们期望 slick.lifted.Query[Nothing,Nothing,Seq] 而它们正在获取 slick.lifted.Query[Nothing,T,Seq]。最后,db.run 语句不想使用 headOption,显然返回不支持 map< 的 Any/

停止

最佳答案

通过最终理解 slick 如何将事物放在一起以进行理解来解决此问题。我不得不将计数从查询中提取出来,并放入后续的 groupby->map 函数中,该函数累积了我想要计数的事物列表,然后对它们进行计数,而不是将其作为查询的一部分进行计数。这也解决了所有其他问题,因为计数查询抛出了其他一切的预期返回类型。

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

val select = (for {
thing1 <- query1
thing2 <- query2
thing3 <- query3
listToCount <- query4 selecting everything I wanted to count
} yield (thing2, thing3, listToCount))
.groupBy({
case (thing2, thing3, listToCount) =>
(thing2, thing3)
})
.map({
case ((thing2, thing3), list) =>
(thing2.deliveryDate, thing3.schedulerJobId, list.map(_._3).length)
})

关于postgresql - 如何使用 slick 在同一事务中运行相互依赖的查询以及非数据库操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51028369/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com