2016-01-17 7 views
10

W swoim projekcie użyciu obiektu typu A który ma OneToMany związek (orphanRemoval = prawda kaskady = CascadeType.ALL, pobrać = FetchType.EAGER) obiektów typu B. Potrzebuję SpringDataRest (SDR) do przechowywania pełnego obiektu A z jego obiektami (dziećmi) przy użyciu pojedynczego żądania POST. Próbowałem kilka kombinacji w SDR, jedyny, który pracował dla mnie, było stworzenie @RepositoryRestResource dla obiektu A i stworzyć @RepositoryRestResource również dla obiektu B, ale znak ten (B) jako eksportowane = false (jeśli w ogóle nie utworzyłem repozytorium z obiektu B, to by nie działało -> tylko Obiekt byłby przechowywany na pojedynczym żądaniu POST, ale nie byłby podrzędny (relacja @OneToMany) typu B; taki sam wynik występuje, jeśli exported = false jest pominięte dla repozytorium B). Czy to jest ok i jedyny sposób, jak to osiągnąć (pojedyncze żądanie POST z przechowywaniem wszystkich obiektów jednocześnie)?Modyfikacja @OneToMany jednostka Spring danych spoczywają, bez jej składowania

Powód, dla którego pytam, w poprzednim przykładzie, że muszę (chciałbym) kontrolować wszystkie obiekty "cyklu życia" przy użyciu repozytorium A. Jestem z nim w porządku, ponieważ relacja jest składem (B nie istnieje poza A). Ale mam poważny problem z edycją (także usunięciem) jednego określonego obiektu typu B przez SDR z wykorzystaniem jego repozytorium macierzystego (ponieważ obiekt nie ma wyeksportowanego własnego repozytorium). Być może nie jest to możliwe z definicji. Próbowałem następujących rozwiązań:

  • patch do "/ A/1/B/2" nie działa -> metoda niedozwolone (w nagłówkach jest "Zezwalaj: GET, DELETE") -> tak, również PUT jest poza pytaniem
  • Json Patch też nie działa - PATCH dla "/ A/1" przy użyciu poprawki json content-type [{"op": "add", "path": "/ B/2" , ....}] -> "brak takiego indeksu w tablicy docelowej" - ponieważ Json Patch używa skalaru "2" po "tablicy" jako indeksu do swojej tablicy. To nie jest praktyczne w świecie Java, gdy relacje są przechowywane w Zestawie obiektów - indeksowanie w ogóle nie ma znaczenia .
  • mogę eksportować repozytorium (eksportowane = true) obiektu B dla manipulowania go „bezpośrednio”, ale w ten sposób chciałbym stracić zdolność do sklepie Cały obiekt z B obiektów w jeden POST prośba jak wspomniałem wcześniej.

to do uniknięcia wysyłania cały A przedmiotu z jednego maleńkim modyfikacji jego B obiektu na wprost, jeżeli jest to możliwe. Dziękuję.

Odpowiedz

4

Udało mi się zmienić encję podrzędną w następujący sposób.Jako próbki użyłem następujące podmioty:

@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; 
} 

mam tylko repozytorium dla One narażone.

(Kim przykłady użyć doskonałe httpie - CLI HTTP client)

Usuwanie elementu za pomocą JSON plaster

Ten przykład usunie drugą pozycję na liście manies. Możesz użyć @OrderColumn, aby upewnić się, że możesz polegać na kolejności elementów listy.

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" 
    } 
] 

Wymiana całą listę za json plastra

Próbka ta zastępuje spis tablicy podanej wartości.

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" 
      } 
     ] 
    } 
] 

Dodawanie elementu do listy za pomocą json poprawkę

Próbka ta dodaje element na końcu listy. Również tutaj klient musi znać długość listy przed aktualizacją. Tak więc kolejność nie ma tu znaczenia.

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" 
     } 
    } 
] 

Mam nadzieję, że to pomoże.

+0

Dziękuję bardzo, Mathias, za wyczerpujący wpis. Moim problemem jest, jak wspomniałem, że używam zbiorów, a nie list (@OrderColumn nie działa z ustawieniem). Pozwól, że zadam ci osobiste pytanie: czy nie uważasz, że używanie "indeksu" zamiast "id" prawdziwego podmiotu z łatwym zapytaniem o odpoczynek to dość "dziwne" rozwiązanie? Wiem, że to jest główny cel JsonPatch (modyfikacja json) ... ale w każdym razie jestem ciekawy, czy można to zrobić inaczej. – rotmajster

+0

Próbuję twoje rozwiązanie do dodawania pozycji do listy i otrzymuję kilka błędów: doing' "op": "add", "path": "/ manies/-", "value": {"name" : "4"} do listy, która nie ma wpisów, daje mi 'osesSpelEvaluationException: EL1004E: Wywołanie metody: Metoda size() nie może być znaleziona na One type', więc próbowałem użyć'/manies', które dało mi 'org .springframework.data.rest.webmvc.json.patch.PatchException: Nie można odczytać {"name": "4"} do klasy org.hibernate.collection.internal.PersistentBag! 'Jakieś pomysły? – joshwa