2016-01-17 5 views
10

In meinem Projekt I-Objekt vom Typ A verwenden, die OneToMany Beziehung hat (orphanRemoval = true, Kaskade = CascadeType.ALL, holt = FetchType.EAGER) auf Objekte des Typs B. Ich brauche SpringDataRest (SDR), um vollständige volle A Objekt mit seinen B Objekte (Kinder) mit einer einzigen POST-Anfrage zu speichern. Ich habe versucht, verschiedene Kombinationen in SDR, die einzige, die für mich gearbeitet, war A @RepositoryRestResource für Objekt zu erstellen und @RepositoryRestResource erstellen auch für Objekt B, aber markieren Sie diese (B) als = false exportiert (wenn ich nicht Repository B überhaupt aus Objekt erstellt haben, würde es nicht funktionieren -> nur Ein Objekt würde auf einzelne POST-Anfrage gespeichert werden, aber nicht seine Kinder (@OneToMany Beziehung) vom Typ B; die Das gleiche Ergebnis tritt auf, wenn exportierte = false für B Repository) weggelassen wird. Ist das in Ordnung und der einzige Weg, wie man es erreicht (einzelne POST-Anfrage mit dem Speichern aller Objekte auf einmal)?Ändern @OneToMany Einheit in Spring Data Erholung ohne seine Repository

Der Grund warum ich frage, in meinem vorherigen Beispiel, ich muss (ich möchte) alle Objekte "lifecycle" mit A 's Repository zu steuern. Ich bin in Ordnung mit ihm, weil A ->B Beziehung Zusammensetzung (B nicht außerhalb von nicht existiert A). Aber ich habe ein ernsthaftes Problem der Bearbeitung (auch Entfernen) eines bestimmten Objekts vom Typ B von SDR mit seinem übergeordneten Repository (seit Objekt B doest kein eigenes Repository exportiert haben). Vielleicht ist das per Definition nicht möglich. Ich habe diese Lösungen ausprobiert:

  • PATCH für "/ A/1/B/2" funktioniert nicht -> Methode nicht erlaubt (in Header ist "Allow: GET, DELETE") -> so, auch PUT kommt nicht in Frage
  • JSON-Patch würde auch nicht funktionieren - PATCH für "/ A/1" mit JSON-Patch content-type [{"op": "hinzufügen", "Pfad": "/ B/2" , ....}] -> "kein solcher Index in Ziel-Array" - weil JSON-Patch verwendet Skalar "2" nach "Array" als Index zu seinem Array. Dies ist in der Java-Welt nicht praktikabel, wenn Relationen in einem Set von Objekten gehalten werden - eine Indexierung hat überhaupt keine Bedeutung .
  • I-Repository exportieren könnte (exportierte = true) des Objekts B für es zu manipulieren „direkt“, aber auf diese Weise würde ich Fähigkeit zu speichern das gesamte Objekt A mit seinen B Objekte in einem einzigen verlieren POST Anfrage wie ich bereits erwähnt habe.

Ich möchte für PUT die ganze Ein Objekt mit einer einzigen kleinen Modifikation seiner B Objekt zu vermeiden, senden, wenn möglich. Danke.

Antwort

4

Ich habe es geschafft, die untergeordnete Entität wie folgt zu ändern.Als Beispiel habe ich die folgenden Einrichtungen:

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

Ich habe nur ein Repository für One ausgesetzt.

(Meine Beispiele verwenden die ausgezeichnete httpie - CLI HTTP client)

ein Element entfernen json Patch mit

Dieses Beispiel das zweite Element in der Manies Liste entfernen. Sie können @OrderColumn verwenden, um sicherzustellen, dass Sie sich auf die Reihenfolge der Listenelemente verlassen können.

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

die gesamte Liste Ersetzen mit json Patch

Dieses Beispiel ersetzt die Liste mit dem Array in dem angegebenen Wert.

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

ein Element zur Liste hinzufügen mit json Patch

Diese Probe fügt das Ende einer Liste ein Element aus. Auch hier muss der Client nur die Länge der Liste vor dem Update wissen. Die Reihenfolge spielt hier also keine Rolle.

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

Hoffe, das hilft.

+0

Vielen Dank, Mathias, für Ihren umfassenden Beitrag. Mein Problem ist, wie ich bereits erwähnt habe, dass ich Sets und keine Listen verwende (@OrderColumn funktioniert nicht mit Set). Lass mich dir eine persönliche Frage stellen: Denkst du nicht, dass die Verwendung von "index" anstelle von "id" einer echten Entität mit einfacher Restabfrage eine ziemlich "seltsame" Lösung ist? Ich weiß, das kommt mit JsonPatch Hauptzweck (JSon zu modifizieren) ... aber egal, ich bin neugierig, ob das auf andere Weise gemacht werden kann. – rotmajster

+0

Ich probiere Ihre Lösung aus, um ein Objekt zur Liste hinzuzufügen und erhalte mehrere Fehler: doing "op": "add", "path": "/ manies/-", "value": {"name" : "4"} 'zu einer Liste, die keine Einträge hat, gibt mir' osesSpelEvaluationException: EL1004E: Methodenaufruf: Methode size() kann nicht auf einem Typ gefunden werden, also habe ich '/ manies' versucht, was mir' org .springframework.data.rest.webmvc.json.patch.PatchException: Konnte {"name": "4"} nicht in org.hibernate.collection.internal.PersistentBag lesen! 'Irgendwelche Ideen? – joshwa