Класс данных Kotlin Нет конструктора String-аргумент с пружинным отдыхом данных - PullRequest
0 голосов
/ 07 мая 2018

Я использую Spring data rest с Kotlin, и если я использую классы данных, ассоциации через uri перестают работать с ошибкой no String-argument constructor/factory method to deserialize from String value

Класс данных

@Entity
data class Comment(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)     
    var id: Long = 0,
    var author: String? = null,
    var content: String? = null,

    @ManyToOne
    var post: Post? = null) {
}

Если вместо этого я использую простой класс, связь работает нормально.

@Entity
class Comment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)     var id: Long = 0
    var author: String? = null
    var content: String? = null

    @ManyToOne
    var post: Post? = null
}

Связь осуществляется через POST-запрос {"author":"John Doe","content":"Dummy Content", "post":"http://localhost:8080/post/33"}

Есть идеи, почему у меня возникает эта ошибка, когда я использую класс данных, и что я могу сделать, чтобы использовать создание ассоциации через uri и продолжать использовать классы данных?

1 Ответ

0 голосов
/ 07 мая 2018

Я провел небольшое исследование и выяснил, что Spring Data Rest использует собственный модуль Джексона для десериализации JSON в сущности JPA: он использует класс PersistentEntityJackson2Module и внутренний класс UriStringDeserializer для разрешения конкретных сущностей из ссылок URI сущностей, http://localhost:8080/post/33 в вашем примере.

Проблема в том, что эта пользовательская десериализация запускается только тогда, когда запускается «стандартная десериализация» Джексона: та, которая использует пустой конструктор, затем использует сеттеры для разрешения и установки полей. В этот момент UriStringDeserializer преобразует строку в конкретную сущность - Post экземпляр вашего примера.

Когда вы используете класс данных, у класса нет ни пустого конструктора, ни сеттера, поэтому в BeanDeserializer#deserializeFromObject методе Джексона он переходит в if (_nonStandardCreation), будучи истинным, оттуда вызов переходит в BeanDeserializerBase#deserializeFromObjectUsingNonDefault, но не передается PersistentEntityJackson2Module больше, и напрямую завершается ошибкой из-за несоответствия типов между аргументом конструктора и значением json.

Похоже, вам нужно создать запрос функции для его реализации. Если вы решите реализовать себя, предоставление _delegateDeserializer для BeanDeserializer может быть началом (не уверен).

Однако я не знаю, как сам JPA в первую очередь играет с классами данных - в конце концов, он отслеживает изменения состояния сущности, но у класса данных не может быть изменений состояния. Таким образом, в конце концов, возможно, не удастся использовать классы данных - лучше помнить.

Примечание: Вы, вероятно, не можете просто расширить / переопределить PersistentEntityJackson2Module, поскольку оно зарегистрировано для нескольких компонентов в RepositoryRestMvcConfiguration

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...