Конечно, я собираюсь опубликовать это здесь.

сии2.5.7 Spring Data REST неправильно выполняетСТАВИТЬ запрос на обновление ресурса, которыйимеет связанные ресурсы, В отличие от запроса PATCH, который работает как положено!

Например,Person имеет много-к-одному сAddres, Если мы выполняем PUT-запрос с SDR v.2.5.6 (Spring Boot v.1.4.3), то все работает нормально. Но если мы переключимся на версию 2.5.7 (то есть на Spring Boot v.1.4.4), то получим ошибку:

Невозможно создать экземпляр Address: нет конструктора аргумента String / метода фабрики для десериализации из значения String

То же самое происходит с другими типами ассоциаций, например, с одним ко многим (однонаправленным и двунаправленным) - см. Мойпример приложения код и тесты.

Эта проблема присутствует ввсе версии Spring Boot начиная с 1.4.4, включая последнюю стабильную версию 1.5.6, а также новейшую версию 2.0.0-SNAPSHOT!

Чтобы обойти эту ситуацию, мы можем просто переключиться на SDR v.2.5.6 (Spring Boot v.1.4.3).

Я подготовилПочтальон коллекция запросов чтобы помочь вам поиграть с проблемой:SDR PUT Issue

ОБНОВЛЕНИЕ 2017-08-14

Я нашел, как избежать ошибкиCan not construct instance of Address: no String-argument constructor/factory method to deserialize from String value.

Так как я используюЛомбок в этом проекте необходимо просто сказать Ломбоку, чтобы он подавлял использование@ConstructorProperties аннотация всгенерированные конструкторы, Итак, я установилlombok.anyConstructor.suppressConstructorProperties=true в файле 'lombok.config' и ошибка исчезла.

К сожалениюновая проблема был найден -Запрос PUT вообще не обновляет связанные объекты!

Пример ниже демонстрирует это. Когда мы пытаемся обновить Персона, изменив его адрес сaddresses/1 (начальное значение) доaddresses/2 - тогда оно остается прежним:addresses/1! Как и предыдущая проблема, эта проблема присутствует ввсе версии Spring Boot начиная с 1.4.4 (SDR - от v.2.5.7).

Я отладил свой проект и обнаружил, что причина проблемы скрыта в методеDomainObjectReader#mergeForPut (видетьего источник) - Этоникогда заменяет связанные ресурсы новыми.

Прежде чем я опубликую этот вопрос наВесенняя ЮРА, пожалуйстасообщите здесь, если у вас есть эта проблема в ваших проектах и ​​что вы думаете об этом.

Вы можете пройти мой тестВот и проверьте его в своих проектах - тест является «автономным» и не зависит от других классов / модулей (я надеюсь, исключая только H2).

@Entity
public class Person {

    private String name;

    @ManyToOne
    private Address address;

    // other stuff
}

@Entity    
public class Address {

    private String street;

    // other stuff
}

Попытка обновить Person:

PUT http://localhost:8080/api/persons/1
{
    "name": "person1u",
    "address": "http://localhost:8080/api/addresses/2"
}

Получение правильного ответа:

{
    "name": "person1u",
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/persons/1"
        },
        "person": {
            "href": "http://localhost:8080/api/persons/1"
        },
        "address": {
            "href": "http://localhost:8080/api/persons/1/address"
        }
    }
}

Затем проверка «нового» адреса человека - адрес не был обновлен:

GET http://localhost:8080/api/persons/1/address
{
    "street": "address1",
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/addresses/1"
        },
        "address": {
            "href": "http://localhost:8080/api/addresses/1"
        }
    }
}

ОБНОВЛЕНИЕ 2017-08-24

Благодаря Скотту С.ответОказалось, что SDR имеетошибка, который описан в двух билетах:DATAREST-1001 а такжеDATAREST-1012.

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

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