【问题标题】:spring data rest kotlin associations POSTspring data rest kotlin 关联 POST
【发布时间】:2018-10-08 17:58:45
【问题描述】:

我按照教程http://www.baeldung.com/spring-data-rest-relationships 进行操作。 我还观察到,我可以通过提供关系链接来直接创建关联。

curl -i -X POST -H "Content-Type:application/json" -d '{"name":"My Library"}' http://localhost:8080/libraries
curl -i -X POST -d '{"title":"Books", "library":"http://localhost:8080/libraries/1"}' -H "Content-Type:application/json" http://localhost:8080/books

当使用常规类时,这在 Java 和 Kotlin 中都可以正常工作。

但是,如果我在 Kotlin 中使用数据类,则会收到以下错误

2018-04-26 14:13:43.730 错误 79256 --- [nio-8080-exec-2] behRestResponseEntityExceptionHandler:org.springframework.http.converter.HttpMessageNotReadableException:JSON 解析错误:无法构造 com 的实例。 baeldung.models.Library(尽管至少存在一个 Creator):没有字符串参数构造函数/工厂方法可以从字符串值反序列化('http://localhost:8080/libraries/1');嵌套异常是 com.fasterxml.jackson.databind.exc.MismatchedInputException:无法构造 com.baeldung.models.Library 的实例(尽管至少存在一个 Creator):没有字符串参数构造函数/工厂方法可以从字符串值反序列化(' http://localhost:8080/libraries/1') 在 [来源:(org.apache.catalina.connector.CoyoteInputStream);行:1,列:29](通过引用链:com.baeldung.models.Book["library"])

我的项目中确实有相关的 kotlin-spring、kotlin-jpa 和 kotlin-noarg 插件。

代码在这里https://github.com/vijaysl/spring-data-rest

【问题讨论】:

    标签: kotlin spring-data spring-data-jpa spring-data-rest jackson-databind


    【解决方案1】:

    Kotlin 数据类非常严格。它基本上是在告诉你,它无法构建你的 POKO,它列出了它尝试的一些方法。其中之一是使用 String 构造函数。其他是通过私有字段操作(这是正常完成的方式)。

    kotlin 中的数据类,如果它们具有声明为 private val name:String 的字段,则转换为(在 java 中)private final String name; 它不能分配给 final 字段(尝试分配给私有字段很脏,但当它是最终的时候是不可能的;JVM 不允许这样做)并且没有 getName()setName() 函数可以用作另一种水合方法。

    一些选项:

    1. 声明您的变量是var 而不是valprivate var name:Stringprivate String name 等价于 java,后者将使用基于字段的(脏)水合。
    2. 为 kotlin 包含一个特定的 kotlin 依赖项来解决这个问题:compile("com.fasterxml.jackson.module:jackson-module-kotlin") 看看this project

    应该为您工作的示例 kotlin 类:

    import org.springframework.hateoas.Identifiable
    import java.time.LocalDate
    import javax.persistence.*
    import javax.validation.constraints.*
    
    @Entity
    data class Employee(@Pattern(regexp = "[A-Za-z0-9]+")
                        @Size(min = 6, max = 32)
                        val name: String,
                        @Email
                        @NotNull
                        val email: String?,
                        @PastOrPresent
                        val hireDate: LocalDate = LocalDate.now(),
    
                        @OneToMany(mappedBy = "employee", cascade = [CascadeType.ALL])
                        val forms:List<Form> = listOf(),
                        @OneToMany(mappedBy = "employee", cascade = [CascadeType.ALL])
                        val reports:List<Report> = listOf(),
                        @Id @GeneratedValue( strategy =  GenerationType.IDENTITY) private val id: Long? = null): Identifiable<Long> {
    
        override fun getId() = id
    
        constructor(name:String): this(name,"$name@foo.com")
    }
    

    【讨论】:

    • 感谢您的宝贵建议。 1. 我更新了实体以使用 val 而不是 var。那是我的疏忽。 2. 仅修复上面的 1 是不够的。我必须删除依赖项 com.fasterxml.jackson.module:jackson-module-kotlin 才能使其正常工作。不确定原因。也许 spring boot 已经包含了 jackson 库。我在github.com/vijaysl/spring-data-rest 中更新了 kotlin 项目示例
    【解决方案2】:

    使用 kotlin 一切正常。

    只需将“数据类”替换为“类”即可。

    Jackson 在“数据类”中找不到空构造函数。并使用其他反序列化器......不是 Uri....

    【讨论】:

      【解决方案3】:

      尝试在主构造函数上添加@JsonCreator(mode = JsonCreator.Mode.DISABLED) 注解。无需禁用com.fasterxml.jackson.module:jackson-module-kotlin

      解释:

      • Kotlin Jackson 模块暗示您的默认构造函数是 JSON 创建者(请参阅KotlinValueInstantiator 类)。
      • 因此,Spring Data REST 不应用其 bean 反序列化器修饰符(应该通过 URI 加载 bean),因为 bean 属性映射不用于创建者属性(构造函数参数)。
      • KotlinValueInstantiator 尝试使用标准反序列化器和实例化器反序列化构造函数参数,这会导致您提到的错误。

      可能的解决方案:

      由于 koltin-jpa 模块为 JPA 添加了默认的空构造函数,您可以通过显式禁用它来指示 Jackson 不要使用 JSON 创建器,而是使用默认的空构造函数。

      例子:

      @Entity
      class Book @JsonCreator(mode = JsonCreator.Mode.DISABLED) constructor(
      
        @ManyToMany
        val libraries: ModifiableList<Library> = ArrayList(),
      
      ): AbstractPersistable<Long>(), Identifiable<Long>
      

      【讨论】:

        猜你喜欢
        • 2019-07-23
        • 2014-04-23
        • 2019-12-25
        • 1970-01-01
        • 2017-04-22
        • 2019-08-14
        • 2018-09-04
        • 2015-04-26
        • 1970-01-01
        相关资源
        最近更新 更多