Scala-Slick:仅执行了一系列操作的一部分
Scala-Slick: only part of sequence of actions executed
有一段代码可以 adds/updates 一个产品,并且还可以将一个或多个标签关联到它。标签实际上被添加到与产品关联的标签组。
我面临的问题是只有 "part" 的 addOrUpdateProductWithTags() 执行。产品已更新或创建,但未添加标签。如果我评论最后一个查询(见评论),那么一切正常。已打开“”以确认这一点。
lazy val pRetId = prods returning prods.map(_.id)
def addTags(keywords: Seq[String]) = {
for {
k <- keywords
} yield {
tags.filter(_.keyword === k).take(1).result.headOption.flatMap {
case Some(tag) => {
Logger.debug("Using existing tag: " + k)
DBIO.successful(tag.id)
}
case None => {
Logger.debug("Adding new tag: " + k)
tags.returning(tags.map(_.id)) += Tag(k, Some("DUMMY"))
}
}
}
}
def addOrUpdateProductWithTags(prod: Product, tagSet: Seq[String]): Future[Option[Long]] = {
// handle add or update product
val prodObject = prod.id match {
case 0L => pRetId += prod
case _ => prods.withFilter(_.id === prod.id).update(prod)
}
val action = for {
pid <- prodObject
tids <- DBIO.sequence(addTags(tagSet))
} yield (tids, pid)
val finalAction = action.flatMap {
case (tids, pid) => {
val prodId = if (prod.id > 0L) prod.id else pid.asInstanceOf[Number].longValue
val delAction = tagGroups.filter(_.prodId === prodId).delete
val tgAction = for {
tid <- tids
} yield {
tagGroups += TagGroup("Ignored-XX", prodId, tid)
}
delAction.flatMap { x => DBIO.sequence(tgAction) }
// IF LINE BELOW IS COMMENTED THEN TagGroup is created else even delete above doesn't happen
prods.filter(_.id === prodId).map(_.id).result.headOption
}
}
db.run(finalAction.transactionally)
}
这是调用此方法的控制器中的片段。我怀疑来电者等待的时间不够长但不确定...
val prod = Prod(...)
val tagSet = generateTags(prod.tags)
val add = prodsService.addOrUpdateProductWithTags(prod, tagSet)
add.map { value =>
Redirect(controllers.www.routes.Dashboard.dashboard)
}.recover {
case th =>
InternalServerError("bad things happen in life: " + th)
}
知道查询出了什么问题吗?
Stack: Scala 2.11.7, play version 2.5.4, play-slick 2.0.0 (slick 3.1)
终于找到解决办法了:
代替以下两行:
delAction.flatMap { x => DBIO.sequence(tgAction) }
prods.filter(_.id === prodId).map(_.id).result.headOption
我将操作与 andThen 运算符组合如下:
delAction >> DBIO.sequence(tgAction) >> prods.filter(_.id === prodId).map(_.id).result.headOption
现在整个序列都被执行了。我仍然不知道原始解决方案有什么问题,但这有效。
有一段代码可以 adds/updates 一个产品,并且还可以将一个或多个标签关联到它。标签实际上被添加到与产品关联的标签组。
我面临的问题是只有 "part" 的 addOrUpdateProductWithTags() 执行。产品已更新或创建,但未添加标签。如果我评论最后一个查询(见评论),那么一切正常。已打开“”以确认这一点。
lazy val pRetId = prods returning prods.map(_.id)
def addTags(keywords: Seq[String]) = {
for {
k <- keywords
} yield {
tags.filter(_.keyword === k).take(1).result.headOption.flatMap {
case Some(tag) => {
Logger.debug("Using existing tag: " + k)
DBIO.successful(tag.id)
}
case None => {
Logger.debug("Adding new tag: " + k)
tags.returning(tags.map(_.id)) += Tag(k, Some("DUMMY"))
}
}
}
}
def addOrUpdateProductWithTags(prod: Product, tagSet: Seq[String]): Future[Option[Long]] = {
// handle add or update product
val prodObject = prod.id match {
case 0L => pRetId += prod
case _ => prods.withFilter(_.id === prod.id).update(prod)
}
val action = for {
pid <- prodObject
tids <- DBIO.sequence(addTags(tagSet))
} yield (tids, pid)
val finalAction = action.flatMap {
case (tids, pid) => {
val prodId = if (prod.id > 0L) prod.id else pid.asInstanceOf[Number].longValue
val delAction = tagGroups.filter(_.prodId === prodId).delete
val tgAction = for {
tid <- tids
} yield {
tagGroups += TagGroup("Ignored-XX", prodId, tid)
}
delAction.flatMap { x => DBIO.sequence(tgAction) }
// IF LINE BELOW IS COMMENTED THEN TagGroup is created else even delete above doesn't happen
prods.filter(_.id === prodId).map(_.id).result.headOption
}
}
db.run(finalAction.transactionally)
}
这是调用此方法的控制器中的片段。我怀疑来电者等待的时间不够长但不确定...
val prod = Prod(...)
val tagSet = generateTags(prod.tags)
val add = prodsService.addOrUpdateProductWithTags(prod, tagSet)
add.map { value =>
Redirect(controllers.www.routes.Dashboard.dashboard)
}.recover {
case th =>
InternalServerError("bad things happen in life: " + th)
}
知道查询出了什么问题吗? Stack: Scala 2.11.7, play version 2.5.4, play-slick 2.0.0 (slick 3.1)
终于找到解决办法了:
代替以下两行:
delAction.flatMap { x => DBIO.sequence(tgAction) }
prods.filter(_.id === prodId).map(_.id).result.headOption
我将操作与 andThen 运算符组合如下:
delAction >> DBIO.sequence(tgAction) >> prods.filter(_.id === prodId).map(_.id).result.headOption
现在整个序列都被执行了。我仍然不知道原始解决方案有什么问题,但这有效。