简体   繁体   English

Play 2 / Scala - 通用反应式 Mongo CRUD - json 序列化

[英]Play 2 / Scala - Generic Reactive Mongo CRUD - json serialization

I`ve found some questions that are very close to my question (eg Play Framework / Scala: abstract repository and Json de/serialization ) but they didnt solve my problem.我发现了一些与我的问题非常接近的问题(例如Play Framework / Scala: abstract repository 和 Json de/serialization ),但它们并没有解决我的问题。

What I`m trying to achieve is an abstraction of my CRUD DAO for the common crud operations.我试图实现的是我的 CRUD DAO 的抽象,用于常见的 crud 操作。

I build a GenericMongoDaoActor for that:我为此构建了一个 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]()
  }

}

The DAOActor handles Entities that inherit abstract class "Entity": DAOActor 处理继承抽象类“实体”的实体:

abstract class Entity {
  val _id: BSONObjectID
}

Currently there are 2 classes that inherit Entity..目前有 2 个类继承 Entity..

As you can see my DOAActor is already context bound to look for Writes[T] in scope..正如您所看到的,我的 DOAActor 已经绑定了上下文,可以在范围内查找 Writes[T] ..

abstract class GenericMongoDaoActor[T <: Entity: Writes]

When I try to build my project like that, it complains that there are no OWrites given to serialize "obj" of type "T" in the update method.当我尝试像这样构建我的项目时,它抱怨没有 OWrites 用于在更新方法中序列化“T”类型的“obj”。

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

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

I couldnt find a way to solve this issue.我找不到解决这个问题的方法。 Please let me know if you can.如果可以,请告诉我。

I had similar problems when I migrated from an earlier version of ReactiveMongo.当我从早期版本的 ReactiveMongo 迁移时,我遇到了类似的问题。 What worked for me was sprinkling around some .as[JsObject] conversions in the various calls to the ReactiveMongo API.对我.as[JsObject]在对 ReactiveMongo API 的各种调用中.as[JsObject]一些.as[JsObject]转换。

So if before I had:所以如果在我之前:

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

I replaced it with:我将其替换为:

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

This seemed to be sufficient, although I am supplying the necessary JSON converter(s) in a slightly different way to you;这似乎是足够的,虽然在提供略微不同的方式给你必要的JSON转换器(S); subclasses of my abstract class have to implement an implicit val fmt:Format[T] member.我的抽象类的子类必须实现一个implicit val fmt:Format[T]成员。 I doubt whether that is important, but it is an approach that seems to be working :-)我怀疑这是否重要,但这是一种似乎有效的方法:-)

You need to use OWrites and OFormat instead of Writes and Format.您需要使用 OWrites 和 OFormat 而不是 Writes 和 Format。 I know OWrites extends Writes and OFormat extends Format, but the reactivemongo version you are using is waiting for OWrites and OFormat, not its super types.我知道 OWrites 扩展了 Writes 并且 OFormat 扩展了 Format,但是您使用的reactivemongo 版本正在等待 OWrites 和 OFormat,而不是它的超类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM