为 class 未找到的情况提供隐式 reader/writer
Provided implicit reader/writer for case class not found
我正在尝试使用 Reactive Mongo 为 mongo 编写一个很好的通用持久性服务,并且我正在努力为我的记录提供隐式 reader/writer class child仁。这是代码。
首先是基本记录class(每个持久记录都必须实现它。
abstract class Record {
val _id: BSONObjectID = BSONObjectID.generate()
}
第二条记录child案例class(非常简单)及其writer/reader(两种可能的方式,宏与评论中的自定义)
case class TestRecord() extends Record {}
object TestRecord {
// implicit object TestRecordWriter extends BSONDocumentWriter[TestRecord] {
// def write(testRecord: TestRecord): BSONDocument = BSONDocument()
// }
//
// implicit object TestRecordReader extends BSONDocumentReader[TestRecord] {
// def read(doc: BSONDocument): TestRecord = TestRecord()
// }
implicit def reader = Macros.reader[TestRecord]
implicit def writer = Macros.writer[TestRecord]
}
然后是服务本身
class MongoPersistenceService[R <: Record] @Inject()()
(implicit ec: ExecutionContext, tag: ClassTag[R]) {
val collectionName: String = tag.runtimeClass.getSimpleName
def db: Future[DefaultDB] = MongoConnectionWrapper.getMongoConnection("mongodb://127.0.0.1", "27017")
.flatMap(_.database("testDb"))
def collection: Future[BSONCollection] = db.map(_.collection(collectionName))
def persist(record: R): Future[Unit] = {
collection.flatMap(_.insert(record)).map(_ => {})
}
def read(id: BSONObjectID): Future[R] = {
for {
coll <- collection
record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
} yield record
}
}
这是我的失败测试:
import scala.concurrent.ExecutionContext.Implicits.global
class MongoPersistenceServiceSpec extends WordSpec with Matchers with BeforeAndAfter {
val persistenceService = new MongoPersistenceService[TestRecord]()
"persist" when {
"called" should {
"succeeds when passing a not persisted record" in {
val testRecord = TestRecord()
persistenceService.persist(testRecord)
val persistedRecord = Await.result(persistenceService.read(testRecord._id), Duration(1000, "millis"))
assert(persistedRecord.eq(testRecord))
}
}
}
}
编译器抱怨以下消息:
Error:(33, 32) could not find implicit value for parameter writer: reactivemongo.bson.BSONDocumentWriter[R]
collection.flatMap(_.insert(record)).map(_ => {})
Error:(33, 32) not enough arguments for method insert: (implicit writer: reactivemongo.bson.BSONDocumentWriter[R], implicit ec: scala.concurrent.ExecutionContext)scala.concurrent.Future[reactivemongo.api.commands.WriteResult].
Unspecified value parameters writer, ec.
collection.flatMap(_.insert(record)).map(_ => {})
Error:(39, 57) could not find implicit value for parameter reader: reactivemongo.bson.BSONDocumentReader[R]
record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
Error:(39, 57) not enough arguments for method one: (implicit reader: reactivemongo.bson.BSONDocumentReader[R], implicit ec: scala.concurrent.ExecutionContext)scala.concurrent.Future[Option[R]].
Unspecified value parameters reader, ec.
record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
有人知道我可能遗漏了什么吗?
我还是 scala 的新手,所以帮我找到这里的问题。
我已经尝试编写自定义 BSONWriter/BSONReader 而不是此处提供的 BSONDocumentWriter/BSONDocumentReader 但没有成功。
您的 persist
函数无法访问您已经定义了那些隐式函数的事实。签名应该是这样的:
def persist(record: R)(implicit def writer: BSONDocumentWriter[R]): Future[Unit]
无论你在哪里调用 persist
并传递 TestRecord
,都要确保隐式函数在范围内。
简而言之,Scala 不会在您的代码中到处搜索隐式。它们需要被纳入范围,要么通过导入,将它们作为参数传递,要么,正如我在这里建议的那样,through a context bound:
class MongoPersistenceService[R <: Record : BSONDocumentReader : BSONDocumentWriter]
这是 (a) 的一种简写形式,要求在使用特定 [=12] 构造 class 时可以找到隐式 BSONDocumentReader[R]
(和编写器) =],以及 (b) 将这些隐含函数引入 class 的实现范围内,以便它们可以隐式传递给其他方法,如 insert
.
为了满足新要求 (a),您可能必须 import TestRecord._
在测试中。
我正在尝试使用 Reactive Mongo 为 mongo 编写一个很好的通用持久性服务,并且我正在努力为我的记录提供隐式 reader/writer class child仁。这是代码。
首先是基本记录class(每个持久记录都必须实现它。
abstract class Record {
val _id: BSONObjectID = BSONObjectID.generate()
}
第二条记录child案例class(非常简单)及其writer/reader(两种可能的方式,宏与评论中的自定义)
case class TestRecord() extends Record {}
object TestRecord {
// implicit object TestRecordWriter extends BSONDocumentWriter[TestRecord] {
// def write(testRecord: TestRecord): BSONDocument = BSONDocument()
// }
//
// implicit object TestRecordReader extends BSONDocumentReader[TestRecord] {
// def read(doc: BSONDocument): TestRecord = TestRecord()
// }
implicit def reader = Macros.reader[TestRecord]
implicit def writer = Macros.writer[TestRecord]
}
然后是服务本身
class MongoPersistenceService[R <: Record] @Inject()()
(implicit ec: ExecutionContext, tag: ClassTag[R]) {
val collectionName: String = tag.runtimeClass.getSimpleName
def db: Future[DefaultDB] = MongoConnectionWrapper.getMongoConnection("mongodb://127.0.0.1", "27017")
.flatMap(_.database("testDb"))
def collection: Future[BSONCollection] = db.map(_.collection(collectionName))
def persist(record: R): Future[Unit] = {
collection.flatMap(_.insert(record)).map(_ => {})
}
def read(id: BSONObjectID): Future[R] = {
for {
coll <- collection
record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
} yield record
}
}
这是我的失败测试:
import scala.concurrent.ExecutionContext.Implicits.global
class MongoPersistenceServiceSpec extends WordSpec with Matchers with BeforeAndAfter {
val persistenceService = new MongoPersistenceService[TestRecord]()
"persist" when {
"called" should {
"succeeds when passing a not persisted record" in {
val testRecord = TestRecord()
persistenceService.persist(testRecord)
val persistedRecord = Await.result(persistenceService.read(testRecord._id), Duration(1000, "millis"))
assert(persistedRecord.eq(testRecord))
}
}
}
}
编译器抱怨以下消息:
Error:(33, 32) could not find implicit value for parameter writer: reactivemongo.bson.BSONDocumentWriter[R]
collection.flatMap(_.insert(record)).map(_ => {})
Error:(33, 32) not enough arguments for method insert: (implicit writer: reactivemongo.bson.BSONDocumentWriter[R], implicit ec: scala.concurrent.ExecutionContext)scala.concurrent.Future[reactivemongo.api.commands.WriteResult].
Unspecified value parameters writer, ec.
collection.flatMap(_.insert(record)).map(_ => {})
Error:(39, 57) could not find implicit value for parameter reader: reactivemongo.bson.BSONDocumentReader[R]
record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
Error:(39, 57) not enough arguments for method one: (implicit reader: reactivemongo.bson.BSONDocumentReader[R], implicit ec: scala.concurrent.ExecutionContext)scala.concurrent.Future[Option[R]].
Unspecified value parameters reader, ec.
record <- coll.find(BSONDocument("_id" -> id)).one[R].mapTo[R]
有人知道我可能遗漏了什么吗? 我还是 scala 的新手,所以帮我找到这里的问题。
我已经尝试编写自定义 BSONWriter/BSONReader 而不是此处提供的 BSONDocumentWriter/BSONDocumentReader 但没有成功。
您的 persist
函数无法访问您已经定义了那些隐式函数的事实。签名应该是这样的:
def persist(record: R)(implicit def writer: BSONDocumentWriter[R]): Future[Unit]
无论你在哪里调用 persist
并传递 TestRecord
,都要确保隐式函数在范围内。
简而言之,Scala 不会在您的代码中到处搜索隐式。它们需要被纳入范围,要么通过导入,将它们作为参数传递,要么,正如我在这里建议的那样,through a context bound:
class MongoPersistenceService[R <: Record : BSONDocumentReader : BSONDocumentWriter]
这是 (a) 的一种简写形式,要求在使用特定 [=12] 构造 class 时可以找到隐式 BSONDocumentReader[R]
(和编写器) =],以及 (b) 将这些隐含函数引入 class 的实现范围内,以便它们可以隐式传递给其他方法,如 insert
.
为了满足新要求 (a),您可能必须 import TestRecord._
在测试中。