代码之家  ›  专栏  ›  技术社区  ›  ivanorone

Slick update操作在数据库中刷新对象之前返回

  •  0
  • ivanorone  · 技术社区  · 7 年前

    我遇到了这样一种情况:当我在更新对象后立即获取对象时,有时从DB获得的结果不包含最新的更改。

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

    我认为update方法只有在成功地将更改刷新到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 回复  |  直到 7 年前
        1
  •  2
  •   Luca T.    7 年前

    问题是你没有考虑内心 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"))
    }
    

    will给了类型为的对象 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
    }
    

    因为,为了理解 <- 平面图