Kotlin数据类没有带有Spring数据其余部分的字符串参数构造函数 [英] Kotlin data class No String-argument constructor with spring data rest
问题描述
我正在将Spring数据与Kotlin结合使用,如果我使用数据类,则通过uri的关联将停止,并出现错误no String-argument constructor/factory method to deserialize from String value
I'm using Spring data rest with Kotlin and if I use data classes the associations via uri stops working with the error 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) {
}
如果我使用简单的类,则关联可以正常工作.
If I use a simple class instead the association works fine.
@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使用关联创建并继续使用数据类?
Any ideia why I have this error when I use a data class and what can I do to use the association creation via uri and keep using data classes?
推荐答案
我做了一些调查,结果发现Spring Data Rest使用自定义的Jackson模块将JSON反序列化为JPA实体:它使用PersistentEntityJackson2Module
类并使用内部类UriStringDeserializer
可以从实体URI引用(在您的示例中为http://localhost:8080/post/33
)解析具体实体.
I did some investigation, and turns out Spring Data Rest uses a custom Jackson module to deserialize JSON into JPA entities: it uses PersistentEntityJackson2Module
class and using the inner class UriStringDeserializer
to resolve the concrete entities from entity URI references, http://localhost:8080/post/33
in your example.
问题是,此自定义反序列化仅在触发Jackson的标准反序列化"时才起作用:使用空构造函数,然后使用setter解析&的程序.设置字段.此时,UriStringDeserializer
会将字符串转换为具体的实体-示例的Post
实例.
Problem is, this custom deserialization only kicks in when the "standard deserialization" of Jackson is triggered: The one that uses empty constructor, then using setters to resolve & set the fields. At that moment, UriStringDeserializer
converts the string into the concrete entity - Post
instance of your example.
当您使用数据类时,该类既没有空的构造函数,也没有设置方法,因此在Jackson的BeanDeserializer#deserializeFromObject
方法中,它分支为if (_nonStandardCreation)
为真,从那里调用进入BeanDeserializerBase#deserializeFromObjectUsingNonDefault
,但没有移交给PersistentEntityJackson2Module
,并且由于构造函数参数和json值之间的类型不匹配而直接失败.
When you use a data class, the class neither has an empty constructor nor setters, therefore in BeanDeserializer#deserializeFromObject
method of Jackson, it branches into if (_nonStandardCreation)
being true, from there the call goes into BeanDeserializerBase#deserializeFromObjectUsingNonDefault
, but not handed over to PersistentEntityJackson2Module
anymore, and directly failing due to type mismatch between the constructor argument and the json value.
似乎您需要创建功能请求才能实现.如果您决定实现自己,则可以将_delegateDeserializer
提供给BeanDeserializer可能是一个开始(不确定).
It seems you need to create a feature request for it to be implemented. If you decide to implement yourself, providing a _delegateDeserializer
to the BeanDeserializer might be a start (not sure).
但是,我首先不知道JPA本身如何处理数据类-毕竟它跟踪实体状态变化,但是数据类不能具有状态变化.因此,可能根本无法使用数据类-最好记住这一点.
However, I don't know how JPA itself plays with data classes in the first place - after all it tracks the entity state changes, but a data class cannot have state changes. So, it might not be possible to use data classes after all - better to keep in mind.
注意:您可能不能简单地扩展/覆盖PersistentEntityJackson2Module
,因为它已在RepositoryRestMvcConfiguration
Note: You probably cannot simply extend/override PersistentEntityJackson2Module
because it is registered to multiple beans in RepositoryRestMvcConfiguration
这篇关于Kotlin数据类没有带有Spring数据其余部分的字符串参数构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!