将值插入持久层并返回结果对象时,通常最好提取新创建的实体,而不是再次返回输入数据。
当我尝试使用reactivemongo在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对象,一切都很好。
我认为我对这里发生的事情有一般性的误解 - 也许有更好的方法可以一次性获取创建的对象。
答案 0 :(得分: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
收益率。