2015-11-08 66 views
1

I`ve发现一些问题,非常接近我的问题(例如Play Framework/Scala: abstract repository and Json de/serialization),但他们没有解决我的问题。播放2 /斯卡拉 - 通用反应蒙戈CRUD - JSON序列

什么我真的想要实现我的CRUD DAO为了共同的CRUD操作的抽象。

我建立一个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处理继承抽象类 “实体” 的实体:

abstract class Entity { 
    val _id: BSONObjectID 
} 

目前有2类,继承实体..

正如你可以看到我的DOAActor已经背景下必然要寻找的范围写道T] ..

abstract class GenericMongoDaoActor[T <: Entity: Writes] 

当我尝试构建我的项目时,它抱怨没有OWrites在update方法中序列化“T”类型的“obj”。

No Json serializer as JsObject found for type T. Try to implement an implicit OWrites or OFormat for this type. 

collection.update(<------------- 

我找不到解决此问题的方法。如果可以,请告诉我。

回答

0

我有类似的问题,当我从ReactiveMongo的早期版本迁移。对我来说有效的是在对ReactiveMongo API的各种调用中转换了一些.as[JsObject]转换。

所以,如果我收到:

collection.update(
    selector, 
    obj, 
    ... 
) 

我取代了它:

collection.update(
    selector, 
    obj.as[JsObject], 
    ... 
) 

这似乎是足够的,虽然我上午提供一个必要的JSON转换器(S)与你略有不同;我的抽象类的子类必须实现一个implicit val fmt:Format[T]成员。我怀疑这是否是重要的,但它是似乎是工作:-)

+0

这解决了我的问题。非常感谢。我仍然不明白为什么它抱怨说,它需要在上面owrites或oformat .. – muenchnair

-1

您需要使用OWrites和OFormat而不是写入和格式的方法。 我知道OWrites扩展了Writes,OFormat扩展了Format,但是你使用的reactivemongo版本正在等待OWrites和OFormat,而不是它的超类型。

+0

这是不可能使用'Writes',而不是'OWrites',写一个结构的特殊性相应预期BSON文件必须是与执行' JsObject',而不是'JsValue'('Writes'的结果)。 – cchantep

+0

@cchantep我说“使用OWrites而不是Writes”。 .as [JsObject]的使用是一种破解,而不是解决方案。 play-reactivemongo的最新版本使用OWrites,OFormat等。我有同样的错误。请阅读错误。 – David