MongoDB Kotlin Driver报错:无法调用数据类User的主构造函数
问题重现
模型类代码
@Serializable actual data class User( @SerialName(value = "_id") actual val id: String = "", actual val username: String = "", actual val password: String = "" )
业务代码
override suspend fun checkUserExistence(user: User): User? { return try { userCollection .find( Filters.and( Filters.eq(User::username.name, user.username), Filters.eq(User::password.name, user.password) ) ).firstOrNull() } catch (e: Exception) { context.logger.error("checkUserExistence ERROR") context.logger.error(e.message.toString()) null } }
错误日志
[Thread-16] DEBUG org.mongodb.driver.operation - Unable to retry the operation find due to the error "org.bson.codecs.configuration.CodecConfigurationException: Unable to invoke primary constructor of User data class"
2023-09-09 07:33:26.780 [eventLoopGroupProxy-4-4] ERROR ktor.application - checkUserExistence ERROR
2023-09-09 07:33:26.780 [eventLoopGroupProxy-4-4] ERROR ktor.application - Unable to invoke primary constructor of User data class
原因分析
该错误核心是MongoDB默认的Codec无法处理带有Kotlinx Serialization注解的数据类,导致从MongoDB查询文档映射到User对象时,无法正确调用主构造函数完成实例化。
解决方案
1. 确认依赖配置
确保项目中引入MongoDB Kotlin序列化驱动及Kotlinx Serialization相关依赖:
// build.gradle.kts 示例 dependencies { implementation("org.mongodb:mongodb-driver-kotlin-coroutine:4.10.1") implementation("org.mongodb:mongodb-driver-kotlin-serialization:4.10.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") }
2. 配置MongoClient使用Kotlinx Serialization Codec
创建MongoClient时,指定使用Kotlinx Serialization的CodecRegistry,替换默认的Codec处理逻辑:
import org.bson.codecs.configuration.CodecRegistries.fromProviders import org.bson.codecs.configuration.CodecRegistries.fromRegistries import org.mongodb.kotlin.client.coroutine.MongoClient import org.mongodb.kotlin.client.coroutine.MongoCollection import kotlinx.serialization.modules.SerializersModule // 若无需自定义序列化逻辑,可直接使用空模块 val serializersModule = SerializersModule {} val codecRegistry = fromRegistries( MongoClientSettings.getDefaultCodecRegistry(), fromProviders(SerializersModuleCodecProvider(serializersModule)) ) // 创建配置好Codec的MongoClient val mongoClient = MongoClient.create( MongoClientSettings.builder() .applyConnectionString(ConnectionString("mongodb://localhost:27017")) .codecRegistry(codecRegistry) .build() ) // 获取指定泛型的User集合 val userCollection: MongoCollection<User> = mongoClient.getDatabase("your_db_name").getCollection("users")
3. 验证字段映射与构造函数
- 确保MongoDB文档中的字段名与User类的
@SerialName注解匹配,比如文档中的_id对应类中的id字段; - 数据类主构造函数参数需覆盖MongoDB文档中所有非空字段,或设置合理默认值(当前代码已满足此要求)。
内容的提问来源于stack exchange,提问作者Stefan

