Весной я пишу такой код для обработки запроса PATCH:
@PatchMapping(path = "/{orderId}", consumes = "application/json")
public Order patchOrder(@PathVariable("orderId") Long orderId, @RequestBody Order patch) {
Order order = repo.findById(orderId).get();
if (patch.getDeliveryName() != null) {
order.setDeliveryName(patch.getDeliveryName());
}
if (patch.getDeliveryStreet() != null) {
order.setDeliveryStreet(patch.getDeliveryStreet());
}
if (patch.getDeliveryCity() != null) {
order.setDeliveryCity(patch.getDeliveryCity());
}
//...
//Check all fields in Order class.
return repo.save(order);
}
Очевидно, здесь есть как минимум два недостатка:
Order. То есть при удалении полей или добавлении новых полей в класс Order этот фрагмент кода также необходимо переписать.Я знаю, что могу выполнить некоторую проверку на null на стороне клиента, например, отправлять только ненулевые поля для выполнения PATCH, но мне интересно, есть ли элегантный способ сделать это? Как сопоставление объектов или другие способы?
@Jai Вау, думаю, я понял. Похоже, я перепутал «не чистое» и «повторяющееся».
@Patrick Я провожу проверку в некоторых случаях, например, в классе домена формы. Но в этой ситуации пустое поле в запросе PATCH не означает недопустимое, это может означать, что это поле остается нетронутым.
Я тоже не считаю, что это неправильно. Но я бы хотел изменить одну вещь: Order order = repo.findById(orderId).get(); на что-то более подходящее, например orElseThrow(), и я также не большой поклонник логики внутри классов контроллеров. Я бы предпочел вызвать сервисный метод и провести там проверку.




Вы можете определить новый тип параметра, например OrderPatch, с дополнительными полями. (Spring выполняет сопоставление с Optional за вас). В теле метода patchOrder () вы можете использовать Optional.orElse () со значением существующего порядка по умолчанию, без операторов if.
Первым делом вместо проверки просто null, как показано ниже:
if (patch.getDeliveryName() != null) {
order.setDeliveryName(patch.getDeliveryName());
}
Вы можете сделать это одной строкой:
order.setDeliveryName(StringUtils.isEmpty(patch.getDeliveryName()) ? "" : patch.getDeliveryName());
Также с помощью метода Spring проверяется наличие нулевых и пустых значений.
А для точки "б" вы можете использовать приведенный ниже код:
BeanUtils.copyProperties(bean2, bean1);
добавить следующую зависимость в pom.xml
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
Перенесите nullchecker в сеттер:
Order order = repo.findById(orderId).get();
order.setByPatch(patch)
внутри класса Order
public void setByPatch(Patch patch){
this.setDeliveryName(patch.getDeliveryName());
this.setDeliveryStreet(patch.getDeliveryStreet());
this.setDeliveryCity(patch.getDeliveryCity());
}
затем добавьте к сеттерам NullCheck ...
=========================================== Или вы можете обратиться к: https://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/html/validation.html
И добавьте @Valid к Order в порядке @RequestBody @Validated Order. А затем установите @NotNull, @NotBlank
Лично я не думаю, что это нечисто - это просто повторение. Если вам случится изменить определение
Order, я бы подумал, что лучше, чтобы эта часть приложения была сломана (во время компиляции). Фактически, если бы я изменил класс предметной области и ничего не сломалось, я бы, вероятно, почувствовал себя параноиком.