В Java REST API, используя PATCH против PUT для обновления объекта

Я собираюсь начать разработку нового API для отдыха на Java. Мой вопрос об использовании PATCH - почему?

Допустим, у нас есть объект с именем Address.java

public class Address {

    @Id
    private Long id

    @NotNull
    private String line1;

    private String line2;       //optional

    @NotNull
    private String city;

    @NotNull
    private String state;   
}

Чтобы создать новый адрес, я бы сделал этот http запрос:

POST http://localhost:8080/addresses

со следующим запросом:

{
    "line1" : "mandatory Address line 1",
    "line2" : "optional  Address line 2",
    "city"  : "mandatory City",
    "state" : "cd"
}

Предположим, что созданная запись имеет идентификатор 1

Соответствующий @RestController AddressResource.java будет иметь этот метод:

@PostMapping(value = "/addresses")
public ResponseEntity<Address> create(@valid Address newAddress) {
    addressRepo.save(newAddress);
}

@valid будет гарантировать, что объект действителен перед сохранением данных в таблице.

Теперь предположим, что я переезжаю из своей квартиры наверх по дому вниз по улице. Если я использую патч, он становится

PATCH http://localhost:8080/addresses/1

с запросом полезной нагрузки:

{
    "line1" : "1234 NewAddressDownTheStreet ST",
    "line2" : null
}

Соответствующий метод @RestController будет:

@PatchMapping(value = "/addresses/{id}")
public ResponseEntity<Address> patchAddress(@PathVariable Long id, Address partialAddress) 
{
    Address dbAddress = addressRepo.findOne(id);
    if (partialAddress.getLine1() != null) {
        dbAddress.setLine1(partialAddress.getLine1());
    }
    if (partialAddress.getLine2() != null) {
        dbAddress.setLine2(partialAddress.getLine2());
    }
    if (partialAddress.getCity() != null) {
        dbAddress.setCity(partialAddress.getCity());
    }
    if (partialAddress.getState() != null) {
        dbAddress.setState(partialAddress.getState());
    }

    addressRepo.save(dbAddress)
}

Теперь, если вы запросите таблицу, мой адрес не будет?

"line1" : "1234 NewAddressDownTheStreet ST",
"line2" : "optional  Address line 2",       <-- INCORRECT. Should be null.
"city"  : "mandatory City",
"state" : "cd"

Как видно, вышеприведенные обновления приводят к неверному значению для line2. Это связано с тем, что в java все переменные экземпляра в классе Address инициализируются нулем (или начальными значениями по умолчанию, если они являются примитивами), когда создается экземпляр класса. Таким образом, нет никакого способа отличить значение line2 от нулевого значения до значения по умолчанию.

Вопрос 1) Есть ли стандартный способ обойти это?

Другим недостатком является то, что я не могу использовать аннотацию @Valid для проверки запроса в точке входа, потому что это только частичное. Таким образом, недопустимые данные могут попасть в систему.

Например, представьте, что есть дополнительное поле со следующим определением:

@Min(0) 
@Max(100)
private Integer lengthOfResidencyInYears, 

И пользователь случайно набрал 190 (когда они действительно имели в виду 19 лет), это не подведет.

Вместо PATCH, если бы я использовал PUT, клиент должен был бы отправить полный объект адреса. Это дает то преимущество, что я могу использовать @Valid, чтобы убедиться, что адрес действительно действителен

Если кто-то делает предположение, что GET ДОЛЖЕН выполняться всегда, прежде чем делать какие-либо обновления, почему бы не использовать PUT over PATCH? Я что-то пропустил?

В сторону

Мой вывод заключается в том, что разработчики, использующие динамически типизированные языки, являются сторонниками использования PATCH, поскольку я не вижу никакой выгоды от использования его со статически типизированной языковой линией Java или C #. Это просто добавляет сложности.

Ответы на вопрос(1)

Ваш ответ на вопрос