I'm making a Spring Boot application. I have an entity there:
@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 ...
}
As you can see, I have validation annotations there. But in my application I need to update the fields partially, e.g. client wants to update Education
fields separately from Category
field.
And the problem is that I cannot use PUT request to do that, because it will update whole object. If the Category
field is actually null
, and I want to update just the Education
fields, I will get ConstraintViolationException
, because the Category
field is null
. But it was null
and I want it to be null
further.
I can use PATCH request to do this:
@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);
}
But the question is: How can I validate my fields partially?
For example, if I send a PATCH request with body:
{
"education":"HIGHER",
"eduName":"MIT",
"eduGraduationDate":"2020-05-05"
}
How can I validate only this 3 fields? Not the whole Employee
object? In this example, as I mentioned above, I want the Category
field to be null
and I don't want to validate it, if it is not included in the patch.
Maybe there are some better approaches to partially update entities, if so - which?
CodePudding user response:
You can create a new DTO object with only fields you want to include for your PATCH call like,
EmployeePatchDto
public class EmployeePatchDto {
// Education related fields
@NotNull
private Education education;
@NotBlank
private String eduName;
@NotNull
private LocalDate eduGraduationDate;
// other fields, getters, setters ...
}
but now you'll still have to be sure that these validations are considered when you call the API.
Also, you can opt to validate your DTO class at controller method level by using @Valid
like this,
public ResponseEntity<Employee> patchEmployee(@PathVariable Long id, @Valid @RequestBody EmployeePatchDto employeeDto) throws JsonPatchException, JsonProcessingException {
I'l leave this resource for you. Read this.