Spring PATCH 请求中的部分 bean 验证
Spring partial bean validation in PATCH request
我正在制作 Spring 启动应用程序。我在那里有一个实体:
@Entity
public class Employee {
@NotNull
private Category category;
// Education related fields
@NotNull
private Education education;
@NotBlank
private String eduName;
@NotNull
private LocalDate eduGraduationDate;
// other fields, getters, setters ...
}
如您所见,我在那里有验证注释。但是在我的应用程序中,我需要部分更新字段,例如客户想要与 Category
字段分开更新 Education
字段。
问题是我不能使用 PUT 请求来执行此操作,因为它会更新整个对象。如果 Category
字段实际上是 null
,而我只想更新 Education
字段,我将得到 ConstraintViolationException
,因为 Category
字段是 null
。但它是 null
,我希望它更进一步 null
。
我可以使用 PATCH 请求来执行此操作:
@PatchMapping(path = "/{id}", consumes = "application/merge-patch+json")
public ResponseEntity<Employee> patchEmployee(@PathVariable Long id, @RequestBody JsonMergePatch jsonMergePatch) throws JsonPatchException, JsonProcessingException {
Employee employee = employeeDataService.findById(id).orElseThrow(() -> new ResourceNotFoundException("Employee not exist: id = " + id));
Employee employeePatched = applyPatchToEmployee(jsonMergePatch, employee);
return ResponseEntity.ok(employeeDataService.save(employeePatched));
}
private Employee applyPatchToEmployee(JsonMergePatch jsonMergePatch, Employee targetEmployee) throws JsonPatchException, JsonProcessingException {
JsonNode patched = jsonMergePatch.apply(objectMapper.convertValue(targetEmployee, JsonNode.class));
return objectMapper.treeToValue(patched, Employee.class);
}
但问题是:我如何才能部分验证我的字段?
例如,如果我发送一个正文为 PATCH 的请求:
{
"education":"HIGHER",
"eduName":"MIT",
"eduGraduationDate":"2020-05-05"
}
如何只验证这 3 个字段?不是整个 Employee
对象?在这个例子中,正如我上面提到的,我希望 Category
字段是 null
并且我不想验证它,如果它不包含在补丁中。
也许有一些更好的方法来部分更新实体,如果是的话 - 哪个?
您可以创建一个新的 DTO 对象,其中仅包含您希望包含在 PATCH 调用中的字段,例如,
EmployeePatchDto
public class EmployeePatchDto {
// Education related fields
@NotNull
private Education education;
@NotBlank
private String eduName;
@NotNull
private LocalDate eduGraduationDate;
// other fields, getters, setters ...
}
但现在您仍然需要确保在调用 API 时考虑这些验证。
此外,您可以选择使用 @Valid
在控制器方法级别验证您的 DTO class,
public ResponseEntity<Employee> patchEmployee(@PathVariable Long id, @Valid @RequestBody EmployeePatchDto employeeDto) throws JsonPatchException, JsonProcessingException {
我把这个资源留给你。 Read this.
我正在制作 Spring 启动应用程序。我在那里有一个实体:
@Entity
public class Employee {
@NotNull
private Category category;
// Education related fields
@NotNull
private Education education;
@NotBlank
private String eduName;
@NotNull
private LocalDate eduGraduationDate;
// other fields, getters, setters ...
}
如您所见,我在那里有验证注释。但是在我的应用程序中,我需要部分更新字段,例如客户想要与 Category
字段分开更新 Education
字段。
问题是我不能使用 PUT 请求来执行此操作,因为它会更新整个对象。如果 Category
字段实际上是 null
,而我只想更新 Education
字段,我将得到 ConstraintViolationException
,因为 Category
字段是 null
。但它是 null
,我希望它更进一步 null
。
我可以使用 PATCH 请求来执行此操作:
@PatchMapping(path = "/{id}", consumes = "application/merge-patch+json")
public ResponseEntity<Employee> patchEmployee(@PathVariable Long id, @RequestBody JsonMergePatch jsonMergePatch) throws JsonPatchException, JsonProcessingException {
Employee employee = employeeDataService.findById(id).orElseThrow(() -> new ResourceNotFoundException("Employee not exist: id = " + id));
Employee employeePatched = applyPatchToEmployee(jsonMergePatch, employee);
return ResponseEntity.ok(employeeDataService.save(employeePatched));
}
private Employee applyPatchToEmployee(JsonMergePatch jsonMergePatch, Employee targetEmployee) throws JsonPatchException, JsonProcessingException {
JsonNode patched = jsonMergePatch.apply(objectMapper.convertValue(targetEmployee, JsonNode.class));
return objectMapper.treeToValue(patched, Employee.class);
}
但问题是:我如何才能部分验证我的字段?
例如,如果我发送一个正文为 PATCH 的请求:
{
"education":"HIGHER",
"eduName":"MIT",
"eduGraduationDate":"2020-05-05"
}
如何只验证这 3 个字段?不是整个 Employee
对象?在这个例子中,正如我上面提到的,我希望 Category
字段是 null
并且我不想验证它,如果它不包含在补丁中。
也许有一些更好的方法来部分更新实体,如果是的话 - 哪个?
您可以创建一个新的 DTO 对象,其中仅包含您希望包含在 PATCH 调用中的字段,例如,
EmployeePatchDto
public class EmployeePatchDto {
// Education related fields
@NotNull
private Education education;
@NotBlank
private String eduName;
@NotNull
private LocalDate eduGraduationDate;
// other fields, getters, setters ...
}
但现在您仍然需要确保在调用 API 时考虑这些验证。
此外,您可以选择使用 @Valid
在控制器方法级别验证您的 DTO class,
public ResponseEntity<Employee> patchEmployee(@PathVariable Long id, @Valid @RequestBody EmployeePatchDto employeeDto) throws JsonPatchException, JsonProcessingException {
我把这个资源留给你。 Read this.