在 Kotlin DTO 中使用 Java 可选

Using Java Optional in Kotlin DTOs

目前我在我的 Kotlin DTO 中使用 Java 8 的 Optional,如下所示:

class dto {
    var prop1: String? = null

    var prop2: Optional<String>? = null
}

它的目的是对于像prop2这样的一些属性,我也想在请求中允许删除。所以DTO中prop2的值理解如下:

null => 什么也不做
非空可选 => 更新值
空可选=>删除值(将值设置为空)

然后在代码中的某个时刻我正在执行以下操作:

dto.prop2?.let {
    // since it is not null, then we either need to update or delete value
    if (it.isPresent) {
        // indicates update value
        entity.prop2 = it.get()
        // then entity will be saved in DB and column will be updated
    } else {
        // indicates delete/erase value
        entity.prop2 = null
        // then entity will be saved in DB and column value will be set to null
    }
}

所以我现在的问题是有一个 Kotlinish 可以实现相同的行为而不必使用 Java Optional?我认为这种方式很复杂,这也意味着必须 isPresent 检查代码中的许多部分。

也许您可以创建一个密封的 class 更新操作层次结构来对此建模。那应该使您的代码非常可读。像这样:

sealed class UpdateableProperty<out T>
data class Update<T>(val value: T) : UpdateableProperty<T>()
object DoNothing : UpdateableProperty<Nothing>()
object Delete : UpdateableProperty<Nothing>()

data class Dto (
   val prop1: UpdateableProperty<String>,
   val prop2: UpdateableProperty<Int?>
)

现在,您可以匹配 属性 来决定要做什么:

when(val prop = dto.prop1) {
    is Update -> repo.update(prop.value)
    is Delete -> repo.delete()
    is DoNothing -> { /* Do nothing */ }
}

为了仅修改资源的某些字段,我将使用 HTTP PATCH 方法。您可以在请求正文中仅发送包含您要修改的字段的地图。

如果要将 prop2 设置为空,请发送 {"prop2":null}。如果要将其修改为新值,请发送{"prop2":"new value"}。如果你什么都不想做,就不要在地图中发送prop2。

但是如果您更喜欢类型更安全的版本,您可以创建这样的 DTO:

data class UpdateProp2DTO(
    val id: String
    val prop2: String?
)

仅当您想要更改时才使用此 DTO prop2,否则就不要使用它。

对于 PATCH 方法,只有创建属性少于资源的 DTO 才有意义。如果您希望能够一次更新所有属性,您可以使用 PUT 方法,然后您只需将整个资源替换为请求正文中提供的 DTO。

您可以在这个问题的已接受答案中找到更多信息:。它指向一个 link 描述如何使用 Spring.