给出数据模型(<-表示外键依赖性)
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
半音
答案 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> }