2016-01-17 2 views
10

В моем проекте я использую объект типа A, который имеет отношение OneToMany (orphanRemoval = верно, каскадный = CascadeType.ALL, принесите = FetchType.EAGER) к объектам типа B. Мне нужен SpringDataRest (SDR), чтобы хранить полный полный файл A с его B объектов (детей) с использованием одного запроса POST. Я попробовал несколько комбинаций в СДР, единственный, который работал для меня, было создание @RepositoryRestResource для объекта A и создать @RepositoryRestResource также для объекта B, но отметить это (B), как экспортироваться = ЛОЖЬ (если я не создал репозиторий вне объекта B вообще, он не сработает ->A объект будет храниться на одном запросе POST, но не его дочерних (отношение @OneToMany) типа B; тот же результат возникает, если exported = false опущен для B репозиторий). Это нормально и единственный способ его достижения (один запрос POST с одновременным хранением всех объектов)?Изменить @OneToMany объекта в Spring Data Rest без своего хранилища

Причина, по которой я прошу, в моем предыдущем примере, я должен (я бы хотел) управлять всеми объектами «жизненный цикл», используя A 's репозиторий. Я хорошо с ним, потому что ->B отношение композиции (B не существует вне ). Но у меня есть серьезная проблема редактирования (также удаления) одного определенного объекта типа B с помощью SDR с использованием его родительского репозитория (поскольку объект B doest не имеет собственного хранилища, экспортированного). Возможно, это невозможно по определению. Я пробовал эти решения:

  • PATCH для "/ A/1/B/2" не работает -> метод не допускается (в заголовках является "Allow: GET, DELETE") -> так, также PUT не может быть
  • Json Patch не будет работать - PATCH для "/ A/1" с использованием json patch content-type [{"op": "add", "path": "/ B/2" , ....}] -> «нет такого индекса в целевом массиве» - поскольку Json Patch использует скалярный «2» после «array» как индекс для своего массива. Это не практично в Java-мире, когда отношения хранятся в наборе объектов. Индексирование не имеет значения .
  • я мог бы экспортировать хранилище (вывозимый = истина) объекта B для манипулировать им «непосредственно», но таким образом я бы потерять способность магазина всего объекта с B объектов в один сингле POST запрос, как я уже говорил ранее.

Я хотел бы избежать отправок всего A объекта с одной крошечной модификацией его B объекта для PUT, если это возможно. Спасибо.

ответ

4

Мне удалось изменить дочерний объект следующим образом.В качестве примера я использовал следующие объекты:

@Entity 
@Data 
@NoArgsConstructor 
public class One { 

    @Id 
    @GeneratedValue 
    private Long id; 

    private String name; 

    @OneToMany(cascade = ALL) 
    private List<Many> manies = new ArrayList<>(); 

} 

@Entity 
@Data 
@NoArgsConstructor 
public class Many { 

    public Many(String name) { 
     this.name = name; 
    } 

    @Id 
    @GeneratedValue 
    private Long id; 

    private String name; 
} 

Я просто хранилище для One открытой.

(Мои примеры использования отлично httpie - CLI HTTP client)

Удаление элемента с помощью JSon патч

Этот пример удалит второй элемент в списке manies. Вы можете использовать @OrderColumn, чтобы убедиться, что вы можете положиться на порядок элементов списка.

echo '[{"op":"remove", "path":"/manies/1"}]' | http PATCH :8080/ones/1 Content-Type:application/json-patch+json -v 

PATCH /ones/1 HTTP/1.1 
Content-Type: application/json-patch+json 

[ 
    { 
     "op": "remove", 
     "path": "/manies/1" 
    } 
] 

Замена весь список с помощью JSon патч

Этот пример заменяет список с массивом указанного в значении.

echo '[{"op":"add", "path":"/manies", "value":[{"name":"3"}]}]' | http PATCH :8080/ones/1 Content-Type:application/json-patch+json -v 

PATCH /ones/1 HTTP/1.1 
Accept: application/json 
Content-Type: application/json-patch+json 

[ 
    { 
     "op": "add", 
     "path": "/manies", 
     "value": [ 
      { 
       "name": "3" 
      } 
     ] 
    } 
] 

Добавление элемента в список с помощью JSon патч

Этот пример добавляет элемент в конец списка. Также здесь клиент просто должен знать длину списка перед обновлением. Таким образом, порядок здесь не имеет никакого значения.

echo '[{"op":"add", "path":"/manies/-", "value":{"name":"4"}}]' | http PATCH :8080/ones/1 Content-Type:application/json-patch+json -v 

PATCH /ones/1 HTTP/1.1 
Accept: application/json 
Content-Type: application/json-patch+json 

[ 
    { 
     "op": "add", 
     "path": "/manies/-", 
     "value": { 
      "name": "4" 
     } 
    } 
] 

Надеюсь, это поможет.

+0

Большое спасибо, Матиас, за ваше всестороннее сообщение. Моя проблема, как я уже упоминал, заключается в том, что я использую Sets, а не списки (@OrderColumn не работает с Set). Позвольте мне задать вам личный вопрос: разве вы не думаете, что использование «индекса» вместо «id» реального объекта с легким запросом на отдых является довольно «странным» решением? Я знаю, это связано с главной целью JsonPatch (для изменения json) ... но в любом случае мне интересно, если это можно сделать по-другому. – rotmajster

+0

Я пытаюсь найти решение для добавления элемента в список, и я получаю несколько ошибок: do' "op": "add", "path": "/ manies/-", "value": {"name" : «4»} 'в список, который не имеет записей, дает мне« osesSpelEvaluationException: EL1004E: вызов метода: метод size() не может быть найден в One type', поэтому я попытался использовать '/ manies', который дал мне' org .springframework.data.rest.webmvc.json.patch.PatchException: Не удалось прочитать {"name": "4"} в класс org.hibernate.collection.internal.PersistentBag! 'Любые идеи? – joshwa

Смежные вопросы