目前,我在Kotlin DTO中使用Java 8的Optional
如下:
class dto {
var prop1: String? = null
var prop2: Optional<String>? = null
}
其目的是对于prop2
之类的某些属性,我也希望允许删除请求。因此,DTO中prop2
的值应理解为:
null =>不执行任何操作非空可选=>更新值空的可选=>删除值(将值设置为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
检查。
也许您可以创建更新操作的密封类层次结构来对此建模。那应该使您的代码更具可读性。像这样的东西:
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?
)
仅当您想更改prop2
时才使用此DTO,否则就不要使用它。
对于PATCH
方法,仅创建属性少于资源的DTO才有意义。如果您希望能够立即更新所有属性,则可以使用PUT
方法,然后只需要用请求正文中提供的DTO替换整个资源即可。
您可以在以下问题的公认答案中找到更多信息:Rest api - update single field of resource。它指向描述如何使用Spring进行操作的链接。