Kotlin 数据 class 没有带 spring 数据剩余的字符串参数构造函数
Kotlin data class No String-argument constructor with spring data rest
我正在使用 Spring Kotlin 的数据,如果我使用数据 classes,通过 uri 的关联将停止工作并出现错误 no String-argument constructor/factory method to deserialize from String value
数据class
@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) {
}
如果我使用简单的 class 代替,则关联工作正常。
@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"}
完成的
知道为什么我在使用数据 class 时会出现此错误吗?我该怎么做才能通过 uri 使用关联创建并继续使用数据 classes?
我做了一些调查,结果 Spring Data Rest 使用自定义 Jackson 模块将 JSON 反序列化为 JPA 实体:它使用 PersistentEntityJackson2Module
class 并使用内部 class UriStringDeserializer
从实体 URI 引用中解析具体实体,在您的示例中为 http://localhost:8080/post/33
。
问题是,此自定义反序列化仅在触发 Jackson 的 "standard deserialization" 时才会启动:使用空构造函数,然后使用 setter 来解析和设置字段的反序列化。在那一刻,UriStringDeserializer
将字符串转换为具体实体 - Post
您示例的实例。
当你使用数据class时,class既没有空构造函数也没有setter,因此在Jackson的BeanDeserializer#deserializeFromObject
方法中,它分支为if (_nonStandardCreation)
是的,从那里调用进入 BeanDeserializerBase#deserializeFromObjectUsingNonDefault
,但不再移交给 PersistentEntityJackson2Module
,并且由于构造函数参数和 json 值之间的类型不匹配而直接失败。
您似乎需要创建一个功能请求才能实现它。如果您决定自己实施,向 BeanDeserializer 提供 _delegateDeserializer
可能是一个开始(不确定)。
但是,我首先不知道 JPA 本身如何处理数据 classes - 毕竟它跟踪实体状态变化,但数据 class 不能有状态变化.因此,毕竟可能无法使用数据 classes - 最好记住。
注意:你可能不能简单地extend/overridePersistentEntityJackson2Module
因为它被注册到RepositoryRestMvcConfiguration
中的多个bean
我正在使用 Spring Kotlin 的数据,如果我使用数据 classes,通过 uri 的关联将停止工作并出现错误 no String-argument constructor/factory method to deserialize from String value
数据class
@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) {
}
如果我使用简单的 class 代替,则关联工作正常。
@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"}
知道为什么我在使用数据 class 时会出现此错误吗?我该怎么做才能通过 uri 使用关联创建并继续使用数据 classes?
我做了一些调查,结果 Spring Data Rest 使用自定义 Jackson 模块将 JSON 反序列化为 JPA 实体:它使用 PersistentEntityJackson2Module
class 并使用内部 class UriStringDeserializer
从实体 URI 引用中解析具体实体,在您的示例中为 http://localhost:8080/post/33
。
问题是,此自定义反序列化仅在触发 Jackson 的 "standard deserialization" 时才会启动:使用空构造函数,然后使用 setter 来解析和设置字段的反序列化。在那一刻,UriStringDeserializer
将字符串转换为具体实体 - Post
您示例的实例。
当你使用数据class时,class既没有空构造函数也没有setter,因此在Jackson的BeanDeserializer#deserializeFromObject
方法中,它分支为if (_nonStandardCreation)
是的,从那里调用进入 BeanDeserializerBase#deserializeFromObjectUsingNonDefault
,但不再移交给 PersistentEntityJackson2Module
,并且由于构造函数参数和 json 值之间的类型不匹配而直接失败。
您似乎需要创建一个功能请求才能实现它。如果您决定自己实施,向 BeanDeserializer 提供 _delegateDeserializer
可能是一个开始(不确定)。
但是,我首先不知道 JPA 本身如何处理数据 classes - 毕竟它跟踪实体状态变化,但数据 class 不能有状态变化.因此,毕竟可能无法使用数据 classes - 最好记住。
注意:你可能不能简单地extend/overridePersistentEntityJackson2Module
因为它被注册到RepositoryRestMvcConfiguration