在 Kotlin 中使用 spring-data-mongodb 时出现异常

Dan*_*iel 3 kotlin spring-data-mongodb

我是 Kotlin 的新手,正在试验 spring-data-mongodb。请参阅下面的示例(此处也可作为具有内存中 MongoDb 的完全可运行的 Maven 项目获得:https : //github.com/danielsindahl/spring-boot-kotlin-example)。

应用程序.kt

package dsitest

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication

@SpringBootApplication
open class Application

fun main(args: Array<String>) {
    SpringApplication.run(Application::class.java, *args)
}
Run Code Online (Sandbox Code Playgroud)

用户.kt

package dsitest

import org.springframework.data.annotation.Id
import org.springframework.data.annotation.PersistenceConstructor
import org.springframework.data.mongodb.core.mapping.Document

@Document(collection = "user")
data class User @PersistenceConstructor constructor(@Id val id: String? = null, val userName: String)
Run Code Online (Sandbox Code Playgroud)

用户库.kt

package dsitest

import org.springframework.data.repository.CrudRepository

interface UserRepository : CrudRepository<User, String>
Run Code Online (Sandbox Code Playgroud)

KotlinIntegrationTest.kt

package dsitest

import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner

@RunWith(SpringRunner::class)
@SpringBootTest
class KotlinIntegrationTest constructor () {

    @Autowired
    lateinit var userRepository : UserRepository;

    @Test
    fun persistenceTest() {
        val user : User = User(userName = "Mary")
        val savedUser = userRepository.save(user)
        val loadedUser = userRepository.findOne(savedUser.id) // Failing code
        println("loadedUser = ${loadedUser}")
    }
}
Run Code Online (Sandbox Code Playgroud)

在运行测试 KotlinIntegrationTest.persistenceTest 时,我在尝试从 MongoDb 检索用户对象时收到以下错误消息:

org.springframework.data.mapping.model.MappingException: No property null found on entity class dsitest.User to bind constructor parameter to!
Run Code Online (Sandbox Code Playgroud)

如果我修改 User 数据类以使 userName 可为空,则一切正常。

data class User @PersistenceConstructor constructor(@Id val id: String? = null,
val userName: String? = null)
Run Code Online (Sandbox Code Playgroud)

我想了解为什么会这样,因为我不希望 userName 可以为空。是否有其他更好的方法可以在 Kotlin 中定义我的 User 类?

非常感谢,丹尼尔

Raf*_* G. 5

是的,这是一个已知问题。您应该检查 User 类的字节码是什么样的。Java 看到带有所有参数的构造函数,并尝试使用第二个参数的空值调用它。

您可以做的是尝试添加@JvmOverloads到您的构造函数中 - 这将强制 Kotlin 编译器生成构造函数的所有版本,因此 Spring Data Mongo 可以选择正确的一个(摆脱 @PersistenceConstructor)。

您还可以定义 1 个没有默认值的构造函数 - 仅适用于基于 Java 的框架,而第二个构造函数具有一些默认值。或者...

当我像现在这样写东西时,我创建了简单的“持久性”数据类,没有任何默认值,这些类映射到/从我的常规域对象(一种对数据库的抽象)。它可能会在开始时产生一些开销 - 但无论如何保持域模型与存储模型的耦合不那么紧密通常是一个好主意。