Play 2 / Scala - Generic Reactive Mongo CRUD - json 序列化
Play 2 / Scala - Generic Reactive Mongo CRUD - json serialization
我发现了一些与我的问题非常接近的问题(例如 ),但它们并没有解决我的问题。
我想要实现的是对常见 CRUD 操作的 CRUD DAO 的抽象。
我为此构建了一个 GenericMongoDaoActor:
abstract class GenericMongoDaoActor[T <: Entity: Writes](implicit inj:Injector, implicit val f:Format[T]) extends Actor with Injectable {
protected val db = inject[DefaultDB]
protected val collectionName: String
protected val collection:JSONCollection
//set to None to use fallback
def defaultSelector(obj:T):Option[JsObject] = None
def fallbackSelector(obj:T) = Json.obj("_id" -> Json.obj("$elemMatch" -> obj._id))
protected def find(jsObject: JsObject) = {
val currentSender = sender
val futureOption = collection
.find(jsObject)
.cursor[T](ReadPreference.primaryPreferred)
.headOption
futureOption.mapTo[Option[T]].flatMap {
case Some(pobj) =>
currentSender ! Some(pobj)
Future{pobj}
case None =>
currentSender ! None
Future{None}
}
}
protected def save(obj:T):Unit = {
update(obj, true)
}
protected def update(obj:T):Unit = {
update(obj, false)
}
private def update(obj:T, upsert: Boolean):Unit = {
val selector = defaultSelector(obj) match {
case None => fallbackSelector(obj)
case Some(sel) => sel
}
collection.update(
selector,
obj,
GetLastError.Default,
upsert).onComplete {
case Failure(e) => Logger.error("[" + this.getClass.getName + "] Couldn`t update " + obj.getClass.getName + ": " + Json.prettyPrint(Json.toJson(obj)), e)
case Success(lastError) => //currentSender ! lastError todo: do something with lastError
}
}
def findAll() = {
collection.find(Json.obj()).cursor[T](ReadPreference.primaryPreferred).collect[List]()
}
}
DAOActor 处理继承抽象的实体 class "Entity":
abstract class Entity {
val _id: BSONObjectID
}
目前有 2 个 class 继承实体..
如您所见,我的 DOAActor 已经绑定了上下文以在范围内查找 Writes[T]。
abstract class GenericMongoDaoActor[T <: Entity: Writes]
当我尝试那样构建我的项目时,它抱怨说在更新方法中没有提供序列化 "obj" 类型 "T" 的 OWrites。
No Json serializer as JsObject found for type T. Try to implement an implicit OWrites or OFormat for this type.
collection.update( <-------------
我找不到解决这个问题的方法。如果可以,请告诉我。
我从早期版本的 ReactiveMongo 迁移时遇到了类似的问题。对我有用的是在对 ReactiveMongo API.
的各种调用中散布一些 .as[JsObject]
转换
所以如果我之前有:
collection.update(
selector,
obj,
...
)
我将其替换为:
collection.update(
selector,
obj.as[JsObject],
...
)
这似乎已经足够了,尽管我是以一种与您略有不同的方式提供必要的JSON转换器;我的摘要 class 的子 classes 必须实现一个 implicit val fmt:Format[T]
成员。我怀疑这是否重要,但这是一种似乎有效的方法:-)
您需要使用 OWrites 和 OFormat 而不是 Writes 和 Format。
我知道 OWrites 扩展了 Writes,OFormat 扩展了 Format,但是您使用的 reactivemongo 版本正在等待 OWrites 和 OFormat,而不是它的超类型。
我发现了一些与我的问题非常接近的问题(例如
我想要实现的是对常见 CRUD 操作的 CRUD DAO 的抽象。
我为此构建了一个 GenericMongoDaoActor:
abstract class GenericMongoDaoActor[T <: Entity: Writes](implicit inj:Injector, implicit val f:Format[T]) extends Actor with Injectable {
protected val db = inject[DefaultDB]
protected val collectionName: String
protected val collection:JSONCollection
//set to None to use fallback
def defaultSelector(obj:T):Option[JsObject] = None
def fallbackSelector(obj:T) = Json.obj("_id" -> Json.obj("$elemMatch" -> obj._id))
protected def find(jsObject: JsObject) = {
val currentSender = sender
val futureOption = collection
.find(jsObject)
.cursor[T](ReadPreference.primaryPreferred)
.headOption
futureOption.mapTo[Option[T]].flatMap {
case Some(pobj) =>
currentSender ! Some(pobj)
Future{pobj}
case None =>
currentSender ! None
Future{None}
}
}
protected def save(obj:T):Unit = {
update(obj, true)
}
protected def update(obj:T):Unit = {
update(obj, false)
}
private def update(obj:T, upsert: Boolean):Unit = {
val selector = defaultSelector(obj) match {
case None => fallbackSelector(obj)
case Some(sel) => sel
}
collection.update(
selector,
obj,
GetLastError.Default,
upsert).onComplete {
case Failure(e) => Logger.error("[" + this.getClass.getName + "] Couldn`t update " + obj.getClass.getName + ": " + Json.prettyPrint(Json.toJson(obj)), e)
case Success(lastError) => //currentSender ! lastError todo: do something with lastError
}
}
def findAll() = {
collection.find(Json.obj()).cursor[T](ReadPreference.primaryPreferred).collect[List]()
}
}
DAOActor 处理继承抽象的实体 class "Entity":
abstract class Entity {
val _id: BSONObjectID
}
目前有 2 个 class 继承实体..
如您所见,我的 DOAActor 已经绑定了上下文以在范围内查找 Writes[T]。
abstract class GenericMongoDaoActor[T <: Entity: Writes]
当我尝试那样构建我的项目时,它抱怨说在更新方法中没有提供序列化 "obj" 类型 "T" 的 OWrites。
No Json serializer as JsObject found for type T. Try to implement an implicit OWrites or OFormat for this type.
collection.update( <-------------
我找不到解决这个问题的方法。如果可以,请告诉我。
我从早期版本的 ReactiveMongo 迁移时遇到了类似的问题。对我有用的是在对 ReactiveMongo API.
的各种调用中散布一些.as[JsObject]
转换
所以如果我之前有:
collection.update(
selector,
obj,
...
)
我将其替换为:
collection.update(
selector,
obj.as[JsObject],
...
)
这似乎已经足够了,尽管我是以一种与您略有不同的方式提供必要的JSON转换器;我的摘要 class 的子 classes 必须实现一个 implicit val fmt:Format[T]
成员。我怀疑这是否重要,但这是一种似乎有效的方法:-)
您需要使用 OWrites 和 OFormat 而不是 Writes 和 Format。 我知道 OWrites 扩展了 Writes,OFormat 扩展了 Format,但是您使用的 reactivemongo 版本正在等待 OWrites 和 OFormat,而不是它的超类型。