将spring-data-mongodb与Kotlin一起使用时的例外情况

时间:2017-01-18 09:04:50

标签: kotlin spring-data-mongodb

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

Application.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)
}

User.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)

UserRepository.kt

package dsitest

import org.springframework.data.repository.CrudRepository

interface UserRepository : CrudRepository<User, String>

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}")
    }
}

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

org.springframework.data.mapping.model.MappingException: No property null found on entity class dsitest.User to bind constructor parameter to!

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

data class User @PersistenceConstructor constructor(@Id val id: String? = null,
val userName: String? = null)

我想了解为什么会这样,因为我不希望userName可以为空。在Kotlin中有一些替代的,更好的方法来定义我的User类吗?

非常感谢, 丹尼尔

1 个答案:

答案 0 :(得分:3)

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

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

您还可以定义1个没有默认值的构造函数 - 仅适用于基于Java的框架,第二个版本默认为您。还是......

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