1

将值插入持久层并返回结果对象时,通常最好获取新创建的实体,而不是再次返回输入数据。

当我尝试使用 reactmongo 在 Scala 中执行此操作时,我偶然发现了我的语言技能。

def create(user: User): Future[User] = {
val newUser = user.createOID()

collection.insert(newUser).map {

  case ok if ok.ok => {
    for {
      createdUser <- this.findOne(BSONDocument("_id" -> newUser._id))
    } yield {

      createdUser match {
        case None => throw new RuntimeException("Could not find just created user")
        case Some(x) => x
      }
    }
  }
  case error => throw new RuntimeException(error.message)
  }
}

findOne 的签名在哪里:

def findOne(query: BSONDocument): Future[Option[User]]

我收到以下错误:

[error]  found   : scala.concurrent.Future[models.User]
[error]  required: models.User
[error]  createdUser <- this.findOne(BSONDocument("_id" -> newUser._id))
[error]              ^

如果我返回 newUser 对象,一切都很好。

我想我对这里发生的事情有一个普遍的误解——也许有一种更好的方法可以一次性获取创建的对象。

4

1 回答 1

1

我会说惯用的 Play/Scala 方法如下

def create(user: User): Future[Option[User]] = {
  val newUser = user.createOID()
  for {
    nu <- collection.insert(newUser)
    createdUser <- findOne(BSONDocument("_id" -> newUser._id))
  } yield {
    createdUser
  }
}

请注意,这确实返回Future[Option[User]],而不是Future[User]在您的代码中。我相信这Option[User]绝对是在这种情况下要走的路,因为它实际上告诉该方法的客户端它不能保证插入会成功(因此不需要运行时异常,因为客户端将.map对该方法的结果执行 - 避免使用异常如果你能优雅地处理它们)。

您还可以检查nu是否ok在产量范围内。

于 2013-11-14T15:13:21.393 回答