2015-04-27 21 views
6

mam jeden do wielu relacji między Team oraz Player, jestem w stanie stworzyć zespół z następującym JSONdane Wiosna odpocząć jeden do wielu usuwania obiektów podrzędnych

{ 
    "id": 1, 
    "name": "MyTeam5", 
    "players": [ 
     { 
      "name": "player5" 
     }, 
     { 
      "name":"player10" 
     } 
    ] 
} 

Jednak gdy próbuję usunąć obiekt dziecko poprzez usunięcie go z listy z poniższej JSON

{ 
     "id": 1, 
     "name": "MyTeam5", 
     "players": [ 
      { 
       "id": 2 
       "name": "player5" 
      } 
     ] 
    } 

pojawia się błąd mówiący

"A collection with cascade=\"all-delete-orphan\" was no longer referenced by the owning entity instance: org.a.c.domain.user.Team.players" 

Oto mój kod zespołu i gracza:

@Data 
@Entity 
public class Team { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    private String name; 

    @JsonManagedReference 
    @OneToMany(mappedBy="team", cascade= CascadeType.ALL, orphanRemoval=true) 
    List<Player> players = new ArrayList<Player>(); 

} 

@Data 
@Entity 
public class Player { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    private String name; 

    @JsonBackReference 
    @ManyToOne 
    @JoinColumn(name = "team_id") 
    private Team team; 
} 

Co robię źle? Jackson jest w stanie idealnie odwzorować jeden do wielu relacji, kiedy tworzę nowy zespół z grupą graczy, ale kiedy aktualizuję/usuwam graczy z Team json, to kończy się to z tym samym błędem. Czy jest możliwe, że kolekcja zostanie odtworzona, dlatego hibernacja rzuca błąd, jeśli tak, to jak mam to naprawić? Proszę pomóc

Odpowiedz

4

Problem, który napotykasz, pochodzi z wymiany listy players. Hibernate musi śledzić, które elementy są usuwane i robi to za pomocą konkretnej implementacji list. "PersistentList" (o ile pamiętam)

Najprawdopodobniej problem polega na tym, że dzwonisz pod numer setPlayers. Skutecznie zastępuje listę nową instancją.

Aby rozwiązać ten problem, masz dwie możliwości:

  • uniknąć wywołanie setPlayers za pomocą getPlayers.remove/add
  • lub modyfikować setPlayers uniknąć ustawiając nową listę, ale zamiast wyczyścić załadowane listę i dodać wszystkie elementy z listy argumentów.

Szybki przykład:

public void setPlayers(List list) { 
    if (this.players == null) { 
     this.players = list; 
    } else { 
     this.players.clear(); 
     this.players.addAll(list); 
     // you might need to take care of bidirectional references here 

} 
+0

Gdzie ten kod się znajduje? To pytanie jest charakterystyczne dla spoczynkowych danych wiosennych, czy jest jakiś sposób na spenetrowanie danych, aby poradzić sobie z tą sytuacją? – Jay

+0

Ten kod byłby ustawieniem wewnątrz jednostki jpa. Nie znam żadnego specyficznego dla tego sposobu spoczynku wiosennych danych. –

+0

Ma sens, dzięki. – Jay

0

Możesz mieć rację, że kolekcja jest zastępowany.

Zakładam, że istnieje TeamRepository, a także PlayerRepository i oba są eksportowane. Oznaczałoby to, że odpowiedź Team ujawnia link players, w którym można umieścić identyfikatory URI graczy, którzy powinni być w zespole. Jeśli gracz nie istnieje, najpierw go utworzysz. Tak właśnie działa usługa Spring Data REST.

Należy również pamiętać, że ujawnianie identyfikatorów bazy danych nie jest dokładnie REST. Identyfikator zasobu to jego identyfikator URI.

0

Miałem ten sam rodzaj problemu przy użyciu wiosennego rozruchu. Aktualizacja wiosna-Boot-starter niepełnych z 1.4.3.RELEASE do 1.4.4.RELEASE rozwiązał problem:

<groupId>org.springframework.boot</groupId> 
<artifactId>spring-boot-starter-parent</artifactId> 
<version>1.4.4.RELEASE</version> 

Pod maską jest aktualizowanie pewne zależności, jeden z nich jest wiosna-data-reszta -webmvc. Zostaje zaktualizowany z wersji 2.5.6.RELEASE do wersji 2.5.7.ZWOLNIENIE:

<groupId>org.springframework.data</groupId> 
<artifactId>spring-data-rest-webmvc</artifactId> 
<version>2.5.7.RELEASE</version> 

To jest ta szczególna aktualizacja zależności, która rozwiązała mój problem.

Nie wiem, czy to błąd, czy funkcja wiosennych danych. Ten przypadek użycia jest naprawdę prosty. Ale ponieważ używanie wszystkich tych ram (spring-data-rest, spring-data-jpa) lub domyślny stack z wiosennego rozruchu dotyczy abstrakcji, wydaje mi się logiczne, że jest to w jakiś sposób obsługiwane przez dane wiosenne, o ile wysłany JSON jest poprawny, a konfiguracja jednostki JPA jest poprawna. Idealnie nie chcę zajmować się specyfikacjami Hibernate.

0

Czy używasz PATCH og PUT?

W przypadku Spring Data Rest, wywołanie PUT spowoduje całkowite zastąpienie zasobu (i jak rozumiem, utworzenie nowej, nieśledzonej kolekcji), natomiast PATCH zaktualizuje tylko częściowo Twoją encję.

W twoim przypadku, powiedziałbym, że używanie PATCH jest poprawnym połączeniem i na podstawie mojego doświadczenia, może czasami rozwiązać ten problem.