我已经开始将一个Spring Boot应用程序从Java迁移到Kotlin.在此之前,一切都运行得很完美.现在我不能更新通过PUT/POST接收的任何实体,因为数据不包含来自数据类的缺省值

一个实体看起来是这样的:

package org.some.soft.domain

import java.util.*
import javax.persistence.*

@Entity
@Table(name = "book_item")
data class BookItem (

    @ManyToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH])
    var book: Book,

    @Column(name = "format", nullable = false)
    var format: BookFormat = BookFormat.HARDCOVER,

    @Column(name = "barcode", nullable = false)
    var barcode: String = "0000000000000",

    @Column(name = "label", unique = true)
    var label: String? = null,

    @Column(name = "isReferenceOnly", nullable = false)
    var referenceOnly: Boolean = false,

    @Column(name = "borrowed")
    var borrowed: Date? = null,

    @Column(name = "dueDate")
    var dueDate: Date? = null,

    @Column(name = "price")
    var price: Double? = null,

    @Column(name = "status", nullable = false)
    var status: BookStatus = BookStatus.AVAILABLE,

    @Column(name = "dateOfPurchase")
    var dateOfPurchase: Date = Date(),

    @Column(name = "publicationDate", nullable = false)
    var publicationDate: Date = Date(),

    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    var id: Long? = null,
)

我通过以下控制器接收数据:

    @PutMapping("/book/items")
    fun updateBookItem(@RequestBody book: @Valid BookItem): ResponseEntity<BookItem> {
        val result = bookService.updateBook(book)
        return ResponseEntity
            .ok()
            .headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, book.id.toString()))
            .body(result)
    }

该服务只是从JPA-Repository(bookItemRepository.save(bookItem))调用了save方法,这就是我收到以下错误的步骤:

NULL not allowed for column "PUBLICATION_DATE"; SQL statement:
update book_item set barcode=?, book_id=?, borrowed=?, date_of_purchase=?, due_date=?, format=?, label=?, price=?, publication_date=?, is_reference_only=?, status=? where id=? [23502-214]

this个教程之后,通过复制来自另一个JHipster项目的Gradle版本,我添加了以下插件:

apply plugin: "kotlin" // Required for Kotlin integration
apply plugin: "kotlin-kapt" // Required for annotations processing
apply plugin: "kotlin-spring" // See https://kotlinlang.org/docs/reference/compiler-plugins.html#spring-support
apply plugin: "kotlin-allopen" // See https://kotlinlang.org/docs/reference/compiler-plugins.html#using-in-gradle
apply plugin: "kotlin-jpa" // See https://kotlinlang.org/docs/reference/compiler-plugins.html#jpa-support
apply plugin: "io.gitlab.arturbosch.detekt"

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}"
    implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlin_version}"


    kapt "org.mapstruct:mapstruct-processor:${mapstructVersion}"
    kapt "org.hibernate:hibernate-jpamodelgen:${hibernateVersion}"
    kapt "org.glassfish.jaxb:jaxb-runtime:${jaxbRuntimeVersion}"

    testImplementation "org.jetbrains.kotlin:kotlin-test-junit:${kotlin_version}"

    testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.MappedSuperclass")
    annotation("javax.persistence.Embeddable")
}

但是我还是遇到了一个问题,那就是Spring Boot没有使用我的数据类的默认值.我也进行了调试,属性没有用它们的缺省值进行初始化.

我还try 将var更改为val,但错误仍然存在

注意:我不会从客户端发送空值.我的请求正文只包含不是null的值

非常提前感谢!

推荐答案

在try 了几种组合后,我终于找到了问题所在.

默认情况下,JPA使用Gradle插件生成的无参数构造函数.在设置缺省值时,主构造函数必须是无参数构造函数,这意味着所有参数都必须是可选的,因此JPA使用它.

以下是我所做的更改:(我将book的默认设置为空,并添加了@NotNull注释)

@Entity
@Table(name = "book_item")
data class BookItem (

    @ManyToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH])
    @NotNull
    var book: Book? = null,

    @Column(name = "format", nullable = false)
    var format: BookFormat = BookFormat.HARDCOVER,

    @Column(name = "barcode", nullable = false)
    var barcode: String = "0000000000000",

    @Column(name = "label", unique = true)
    var label: String? = null,

    @Column(name = "isReferenceOnly", nullable = false)
    var referenceOnly: Boolean = false,

    @Column(name = "borrowed")
    var borrowed: Date? = null,

    @Column(name = "dueDate")
    var dueDate: Date? = null,

    @Column(name = "price")
    var price: Double? = null,

    @Column(name = "status", nullable = false)
    var status: BookStatus = BookStatus.AVAILABLE,

    @Column(name = "dateOfPurchase")
    var dateOfPurchase: Date = Date(),

    @Column(name = "publicationDate", nullable = false)
    var publicationDate: Date = Date(),

    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    var id: Long? = null,
)

这解决了我所有的问题.

Kotlin相关问答推荐

扩展属性委托给实例属性

generic 类实例列表 - 调用采用 T 的函数

使用 Kotlin 的 Springboot 中缺少 ResponseEntity 正文属性

Rabin-Karp字符串匹配的实现(Rolling hash)

如何使用成员引用在 Kotlin 中创建属性的分层路径

为什么 Kotlin 在 sumOf 函数 lambda 中默认不将数字视为Int?

Kotlin SAM/功能接口抛出 AbstractMethodError

是什么让 Kotlin 中的 String 类能够使用方括号?

关于 Kotlin 函数类型转换的问题

如何在 Kotlin 中使用具有继承的泛型

具有多个不同类型来源的 LiveData

Kotlin - mutableMapOf() 会保留我输入的顺序

无法为 retrofit2.Call 调用无参数构造函数

使用 clear() 删除 EncryptedSharedPreferences 不起作用

如何在 Android Studio 3.1.3 中查看 Kotlin 中有趣的源代码?

什么是开放式property?为什么我不能将其设置器设为private私有?

如何在协程之外获取 Flow 的值?

使用 kotlin 每 3 位数添加逗号或点

将字符串编码为Kotlin中的UTF-8

尾随 lambda 语法(Kotlin)的目的是什么?