Исключение при использовании Spring-data-mongodb с Kotlin

Я новичок в Котлине и экспериментирую с spring-data-mongodb. См. Пример ниже (также доступен здесь как полностью исполняемый проект Maven с встроенной памятью MongoDb: 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 я получаю следующее сообщение об ошибке при попытке получить объект User из MongoDb:

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

Если я изменяю класс данных пользователя, чтобы имя пользователя было равно NULL, все работает.

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

Я хотел бы понять, почему это так, поскольку я не хочу, чтобы имя пользователя было равно NULL. Есть ли альтернатива, лучший способ определить мой класс User в Котлине?

Большое спасибо, Даниэль

Да, это известная проблема. Вы должны проверить, как выглядит байт-код для вашего класса User. Java видит конструктор со всеми присутствующими параметрами и пытается вызвать его с нулевым значением для второго.

Что вы можете сделать, это попробовать добавить @JvmOverloads к вашему конструктору – это заставит компилятор Kotlin генерировать все версии конструктора, и поэтому Spring Data Mongo может выбрать правильный (избавиться от @PersistenceConstructor).

Вы также можете определить 1 конструктор без параметров по умолчанию – только для фреймворков на основе Java, а второй – с некоторыми стандартными настройками, которые вы используете. Или…

Когда я пишу такие вещи, как вы сейчас, я создаю простые классы данных «persistence» без каких-либо значений по умолчанию, которые отображаются на / из моих обычных объектов домена (своего рода абстракция над базой данных). Вначале это может привести к некоторым накладным расходам, но, тем не менее, поддерживать модель домена не так тесно с моделью хранения, как правило, является хорошей идеей.