一尘不染

如何在Spring Rest Controller中区分null和未提供的值以进行部分更新

json

我试图在Spring Rest Controller中使用PUT请求方法部分更新实体时区分空值和未提供值。

以以下实体为例:

@Entity
private class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /* let's assume the following attributes may be null */
    private String firstName;
    private String lastName;

    /* getters and setters ... */
}

我的人资料库(Spring数据):

@Repository
public interface PersonRepository extends CrudRepository<Person, Long> {
}

我使用的DTO:

private class PersonDTO {
    private String firstName;
    private String lastName;

    /* getters and setters ... */
}

我的Spring RestController:

@RestController
@RequestMapping("/api/people")
public class PersonController {

    @Autowired
    private PersonRepository people;

    @Transactional
    @RequestMapping(path = "/{personId}", method = RequestMethod.PUT)
    public ResponseEntity<?> update(
            @PathVariable String personId,
            @RequestBody PersonDTO dto) {

        // get the entity by ID
        Person p = people.findOne(personId); // we assume it exists

        // update ONLY entity attributes that have been defined
        if(/* dto.getFirstName is defined */)
            p.setFirstName = dto.getFirstName;

        if(/* dto.getLastName is defined */)
            p.setLastName = dto.getLastName;

        return ResponseEntity.ok(p);
    }
}

请求缺少属性

{"firstName": "John"}

预期行为:更新firstName= "John"(保留lastName不变)。

具有空属性的请求

{"firstName": "John", "lastName": null}

预期行为:更新firstName="John"并设置lastName=null

我无法区分这两种情况,因为lastName在DTO中,总是null由Jackson 设置。

注意:我知道REST最佳实践(RFC 6902)建议使用PATCH而不是PUT进行部分更新,但是在我的特定情况下,我需要使用PUT。


阅读 319

收藏
2020-07-27

共1个答案

一尘不染

实际上,如果忽略验证,您可以像这样解决您的问题。

   public class BusDto {
       private Map<String, Object> changedAttrs = new HashMap<>();

       /* getter and setter */
   }
  • 首先,为您的dto编写一个超类,例如BusDto。
  • 其次,更改dto来扩展超类,并更改dto的set方法,以将属性名称和值放置到changedAttrs中(因为当属性具有null值或非null值时,spring都会调用set)。
  • 第三,遍历地图。
2020-07-27