java Spring数据-静止:通过PATCH请求设置空值

46scxncf  于 2023-08-02  发布在  Java
关注(0)|答案(3)|浏览(109)

我想通过发送null请求将null值设置为实体。
举例来说:

PATCH: "{deleteDate: null}" to http://localhost/api/entity/1

字符串
但它不起作用。
我找到了here如何处理PATCH请求的信息:

  • 创建了一个新的Foo示例
  • Foo填充了与请求一起发送的所有值
  • 将加载具有URI提供的id的Foo实体
  • 两个对象之间所有不同的属性都将从新的Foo复制到持久化的Foo中,除非新的Foo中的值为null。

我是否正确地理解了不可能通过对spring-data-rest服务API的PATCH请求将value设置为NULL?

neskvpey

neskvpey1#

在Spring上下文中,PATCH方法中的null值意味着没有更改。如果你想写空值,你可以
1)使用PUT方法;
2)实现您自己DomainObjectMerger类,您可以在其中使用以下条件扩展方法合并:

sourceValue != targetValue;

字符串
3)使用DomainObjectMerger.NullHandlingPolicy配置。
取决于Spring Data REST版本。

mm9b1k5b

mm9b1k5b2#

egorlitvinenko's answer中的所有3个选项都将解决所描述的问题,但会有另一个问题:

  • PATCH request中未指定的所有其他属性也将被“无效”。

似乎 spring-data-restissue-345已经在v2.2.x中修复。

c86crjj0

c86crjj03#

可以使用Map<String,Object>作为请求体,然后可以在map上使用forEach提取数据。
示例控制器:

@PatchMapping("api/entity/{entityId}")
ResponseEntity<EntityDto> modifyEntity(@PathVariable UUID entityId,
        @RequestBody Map<String, Object> modifyEntityData) {

    EntityDto modifiedEntity = entityService
            .modifyEntity(entityId, modifyEntityData);

    return ResponseEntity
            .status(HttpStatus.OK)
            .body(modifiedEntity );
}

字符串
示例服务:

@Transactional
public EntityDto modifyEntity(UUID entityId, Map<String, Object> modifyEntityData) {

    // I assume you have a method that returns Entity by its Id in service
    Entity entityToModify = findEntity(entityId);

    entityToModify = applyChangesToEntity(entityToModify, modifyEntityData);

    // And mapper that returns dto (ofc optional)
    return EntityMapper.mapEntityToDto(entityToModify);
}

private EntityDto applyChangesToEntity(Entity exisistingEntity, 
                                       Map<String, Object> modifyEntityData) {

    modifyEntityData.forEach((key, value) -> {
        switch (key) {
            case "deleteDate" -> {
                // Check if null
                if (value == null) {
                    exisistingEntity.setDeleteDate(null);
                    break;
                }

                // If value is present you can do w/e you want 
                if (validateValueOk(value)) {
                    exisistingEntity.setDeleteDate(value.toString());
                } else {
                    throw new RuntimeException("DeleteDate must be valid or other message");
                }
            }
            // HERE MORE CASES
            default -> throw new RuntimeException("Message");
        }
    });

    return exisistingEntity;
}

相关问题