2015-11-08 41 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