在数据库中刷新对象之前,将返回光滑的更新操作

时间:2018-03-04 12:30:51

标签: scala asynchronous playframework slick

我遇到的情况是,当我在更新后立即获取对象时,有时我从数据库获得的结果不包含最新的更改。

这使我认为更新线程在对象实际在DB中提交之前返回。这是预期的行为吗?

我认为更新方法只会在将更改成功刷新到数据库后才会返回,但看起来不能保证。

下面是伪代码,展示了我在说什么。

def processObject = {
  for {
    objectId: Option[Long] <- saveObjectInDb

    _ <- {
     //perform other synchronous business logic and then update created object details
      dao.findById(objectId.get).map { objectOption: Option[MyObject] =>
        dao.update(objectOption.get.copy(processingStep = "third-step"))
      }
    }

    mostRecentMyObject <- dao.findById(objectId.get)
  } yield mostRecentMyObject
}

以下是我update逻辑的样子

def update(myObject: MyObject): Future[Int] = {
  db.run(table.filter(_.id === myObject.id).update(myObject))
}

1 个答案:

答案 0 :(得分:2)

问题在于您没有考虑Future方法返回的内部update

鉴于findById的签名:

def findById(id: Long): Future[Option[MyObject]]

摘录:

dao.findById(objectId.get).map { objectOption: Option[MyObject] =>
  dao.update(objectOption.get.copy(processingStep = "third-step"))
}

将提供Future[Future[Int]]类型的对象。

您应该在flatMap的未来代替map代替findById,如下所示:

dao.findById(objectId.get).flatMap { objectOption: Option[MyObject] =>
  dao.update(objectOption.get.copy(processingStep = "third-step"))
}

这将简化为单个未来(Future[Int]),因此您只需在插入后检索对象即可。

此外,您可以将其重写为:

def processObject = {
  for {
    objectId: Option[Long] <- saveObjectInDb

    objectOption <- dao.findById(objectId.get)

    _ <- dao.update(objectOption.get.copy(processingStep = "third-step"))

    mostRecentMyObject <- dao.findById(objectId.get)
  } yield mostRecentMyObject
}

因为,为了理解,<-flatMap的语法糖