【问题标题】:Unable to use Mongo Scala driver with case classes无法将 Mongo Scala 驱动程序与案例类一起使用
【发布时间】:2019-08-01 21:45:39
【问题描述】:

我正在尝试将 Scala mongo 驱动程序与案例类一起使用,如下所述:http://mongodb.github.io/mongo-scala-driver/2.2/getting-started/quick-tour-case-classes/

但是我得到了例外:

Can't find a codec for class com.foo.model.User$. org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class com.foo.model.User$.

当我尝试插入一个项目时。

案例类:

case class User(
               _id: ObjectId,
                foo: String = "",
                foo2: String = "", 
                foo3: String = "",
                first: String,
                last: String,
                username: String,
                pwHash: String = ""
                gender: String,
                isFoo: Boolean = false)
extends FooTrait

代码:

val providers = fromProviders( classOf[User])

val registry = fromRegistries(providers, DEFAULT_CODEC_REGISTRY)

val connStr = "mongodb://...."

val clusterSettings = ClusterSettings.builder().applyConnectionString(new ConnectionString(connStr)).build()
        val clientSettings = MongoClientSettings.builder().codecRegistry(getCodecRegistry).clusterSettings(clusterSettings).build()

val client = MongoClient( clientSettings )
val database: MongoDatabase = client.getDatabase(dbName).withCodecRegistry(registry)

val modelCollection: MongoCollection[User] = db.getCollection("user")

val item = User(.....) //snipped
modelCollection.insertOne(item).toFuture()

完整的堆栈跟踪:

Can't find a codec for class com.foo.model.User$.
org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class com.foo.model.User$.
    at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
    at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
    at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)
    at com.mongodb.async.client.MongoCollectionImpl.getCodec(MongoCollectionImpl.java:1170)
    at com.mongodb.async.client.MongoCollectionImpl.getCodec(MongoCollectionImpl.java:1166)
    at com.mongodb.async.client.MongoCollectionImpl.executeInsertOne(MongoCollectionImpl.java:519)
    at com.mongodb.async.client.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:501)
    at com.mongodb.async.client.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:496)
    at org.mongodb.scala.MongoCollection.$anonfun$insertOne$1(MongoCollection.scala:410)
    at org.mongodb.scala.MongoCollection.$anonfun$insertOne$1$adapted(MongoCollection.scala:410)
    at org.mongodb.scala.internal.ObservableHelper$$anon$2.apply(ObservableHelper.scala:42)
    at org.mongodb.scala.internal.ObservableHelper$$anon$2.apply(ObservableHelper.scala:40)
    at com.mongodb.async.client.SingleResultCallbackSubscription.requestInitialData(SingleResultCallbackSubscription.java:38)
    at com.mongodb.async.client.AbstractSubscription.tryRequestInitialData(AbstractSubscription.java:151)
    at com.mongodb.async.client.AbstractSubscription.request(AbstractSubscription.java:82)
    at org.mongodb.scala.ObservableImplicits$BoxedSubscription.request(ObservableImplicits.scala:474)
    at org.mongodb.scala.ObservableImplicits$ScalaObservable$$anon$2.onSubscribe(ObservableImplicits.scala:373)
    at org.mongodb.scala.ObservableImplicits$ToSingleObservable$$anon$3.onSubscribe(ObservableImplicits.scala:440)
    at org.mongodb.scala.Observer.onSubscribe(Observer.scala:85)
    at org.mongodb.scala.Observer.onSubscribe$(Observer.scala:85)
    at org.mongodb.scala.ObservableImplicits$ToSingleObservable$$anon$3.onSubscribe(ObservableImplicits.scala:432)
    at com.mongodb.async.client.SingleResultCallbackSubscription.<init>(SingleResultCallbackSubscription.java:33)
    at com.mongodb.async.client.Observables$2.subscribe(Observables.java:76)
    at org.mongodb.scala.ObservableImplicits$BoxedObservable.subscribe(ObservableImplicits.scala:458)
    at org.mongodb.scala.ObservableImplicits$ToSingleObservable.subscribe(ObservableImplicits.scala:432)
    at org.mongodb.scala.ObservableImplicits$ScalaObservable.headOption(ObservableImplicits.scala:365)
    at org.mongodb.scala.ObservableImplicits$ScalaObservable.head(ObservableImplicits.scala:351)
    at org.mongodb.scala.ObservableImplicits$ScalaSingleObservable.toFuture(ObservableImplicits.scala:410)

我认为我做的一切都是正确的——除非这是一个错误,否则代码应该可以工作。我的mongo-scala-driver 版本是2.2.0

有什么想法吗?

【问题讨论】:

    标签: mongodb scala


    【解决方案1】:

    这是一个使用 Mongo 3.6.1 在我的本地机器上运行的示例。

    // ammonite script mongo.sc
    import $ivy.`org.mongodb.scala::mongo-scala-driver:2.2.0`
    
    import org.mongodb.scala._
    import org.mongodb.scala.connection._
    import org.mongodb.scala.bson.ObjectId
    import org.mongodb.scala.bson.codecs.Macros._
    import org.mongodb.scala.bson.codecs.DEFAULT_CODEC_REGISTRY
    import org.bson.codecs.configuration.CodecRegistries.{fromRegistries, fromProviders}
    
    trait FooTrait
    
    case class User(_id: ObjectId,
                    foo: String = "",
                    foo2: String = "",
                    foo3: String = "",
                    first: String,
                    last: String,
                    username: String,
                    pwHash: String = "",
                    gender: String,
                    isFoo: Boolean = false) extends FooTrait
    
    val codecRegistry = fromRegistries(fromProviders(classOf[User]), DEFAULT_CODEC_REGISTRY )
    
    import scala.collection.JavaConverters._
    val clusterSettings: ClusterSettings = ClusterSettings.builder().hosts(List(new ServerAddress("localhost")).asJava).build()
    val settings: MongoClientSettings = MongoClientSettings.builder().clusterSettings(clusterSettings).build()
    val mongoClient: MongoClient = MongoClient(settings)
    
    val database: MongoDatabase = mongoClient.getDatabase("mydb").withCodecRegistry(codecRegistry)
    val userCollection: MongoCollection[User] = database.getCollection("user")
    
    val user:User = User(new ObjectId(), "foo", "foo2", "foo3", "first", "last", "username", "pwHash", "gender", true)
    
    import scala.concurrent.duration._
    import scala.concurrent.Await
    // wait for Mongo to complete insert operation
    Await.result(userCollection.insertOne(user).toFuture(),3.seconds)
    

    当您将此 sn-p 保存到文件 mongo.sc 中时,您可以使用 Ammonite 运行它

    amm mongo.sc
    

    如果 mongo 在默认端口上运行,则应自动创建 mydb 数据库,包括新的 user 集合。

    【讨论】:

    • 嗯。我想我的唯一不同之处在于,我从定义抽象方法的特征DbService[T] 扩展:def collection = Collection[T]def insert(item: T) = collection.insertOne(item),然后由实现Collection[User]UserService extends DbService[User] 扩展。但是,除非我在 DbService 中也有 implicit def ct: ClassTag[T],否则这是行不通的,这在 UserService 中表示为:ClassTag(classOf[User])。这可能是它对我不起作用的原因,可能是它使用类标签而不是案例类来生成。编解码器?
    • 我的其余代码都是一样的,只是插入和收集是通过DbService和UserService获取的
    • 看起来异常是由于编解码器注册表不完整而触发的。在上面的脚本中将val codecRegistry = fromRegistries(fromProviders(classOf[User]), DEFAULT_CODEC_REGISTRY ) 替换为val codecRegistry = fromRegistries( DEFAULT_CODEC_REGISTRY ) 时,您应该会看到您在问题中提到的相同异常。
    猜你喜欢
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    相关资源
    最近更新 更多