2014-03-24 7 views
13

Ich benutze Jackson, um mein JPA-Modell in JSON zu serialisieren.Serialisieren bidirektionale JPA-Entitäten zu JSON mit Jackson

Ich habe die folgenden Klassen:

import com.fasterxml.jackson.annotation.*; 
import javax.persistence.*; 
import java.util.Set; 

@JsonInclude(JsonInclude.Include.NON_NULL) 
@JsonIgnoreProperties(ignoreUnknown = true) 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class) 
@Entity 
public class Parent { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 
    private String name; 

    @JsonManagedReference 
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    private Set<Child> children; 

    //Getters and setters 
} 

und

import com.fasterxml.jackson.annotation.*; 
import javax.persistence.*; 
import java.util.HashSet; 
import java.util.Set; 

@JsonInclude(JsonInclude.Include.NON_NULL) 
@JsonIgnoreProperties(ignoreUnknown = true) 
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) 
@Entity 
public class Child { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 
    private String name; 

    @JsonBackReference 
    @ManyToOne 
    @JoinColumn(name = "parentId") 
    private Parent parent; 

    //Getters and setters 
} 

ich das POJO-Mapping bin mit von Modell zu JSON serialisiert. Wenn ich einen Elternteil Objekt serialisiert erhalte ich die folgende JSON:

{ 
    "id": 1, 
    "name": "John Doe", 
    "children": [ 
    { 
     "id": 1, 
     "name": "child1" 
    },{ 
     "id": 2, 
     "name": "child2" 
    } 
    ] 
} 

Aber als ich ein Kind ich folgende JSON erhalten serialisiert: an die Mutter

{ 
    "id": 1, 
    "name": "child1" 
} 

Die Referenz fehlt. Gibt es eine Möglichkeit, dies zu lösen?

+0

ist es nicht schlimm, UI-bezogene Logik, z. B. JSON-Annotationen in eine Entität zu integrieren? Ist das nicht Modularisierung? – faisalbhagat

+3

um ... nein.Das ist der Hauptgrund, warum Entitäten existieren: als Datamodell-Repräsentation, sei es JPA, XML, JSON oder sogar eine Kombination von diesen. Wenn Ihre gesamte App einen einzigen Satz von Entitäten verwendet, ist dies ein Indikator für eine gut gestaltete App - ein einzelner Satz von Entitäten führt zu einem einzigen Fehlerpunkt, der die App im Gegenzug in viel höherem Maße wartbar (und austauschbar) macht. – specializt

Antwort

24

Ich denke, Sie müssen zwischen der @ JsonIdentityInfo und der @ JsonBackReference/@ JsonManagedReference wählen.

Ich würde gehen mit: @JsonIdentityInfo (Generator = ObjectIdGenerators.PropertyGenerator.class, Eigenschaft = "ID") auf Ihre Entitäten, entfernt @ JsonBackReference/@ JsonManagedReference-Paare.

Und fügen Sie @ JsonIgnore zu den Feldern hinzu, die Sie ausschließen möchten.

3

Das Problem ist, dass die Verwendung von verwalteten/zurück Referenzen erfordert, dass die Richtung der Traversierung immer von Eltern zu Kind ist (dh verwaltete Referenz zuerst). Dies ist eine Einschränkung für diese Anmerkungen.

Wie die andere Antwort nahelegt, ist die Verwendung von Object Ids die flexiblere Alternative, die vielleicht funktionieren könnte.

Eine andere Option, die vielleicht funktionieren könnte, wäre, JSON-Ansichten oder JSON-Filter zu verwenden, um Elternreferenz bedingt einzuschließen/auszuschließen, wenn Sie Fälle trennen können. Dies könnte unordentlich werden.

5

Sie können JsonManagedReference/JsonBackReference verwenden und gleichzeitig JsonIdentityInfo verwenden, um bidirektionale Beziehungen zu ergänzen.

In Frage Klasse:

// bi-directional one-to-many association to Answer (Question is owner) 
@JsonManagedReference 
@OneToMany(mappedBy = "question", cascade = CascadeType.ALL) 
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@QuestionAnswers") 
private Set<Answer> answers = new HashSet<>(); 

In Antwort Klasse: // bidirektionale Viele-zu-Eins-Zuordnung

@JsonBackReference 
@ManyToOne 
@JoinColumn(name = "questionId", referencedColumnName="id", foreignKey = @ForeignKey(name = "fk_answer_question")) 
private Question question; 

auf Frage Wenn Sie übergeordnete Referenz in Child-Objekt benötigen, entfernen Managed/Back Reference, das funktioniert gut für mich.

+0

Was ist property = "@QuestionAnswers"? Soweit ich verstanden habe, sind die Namen der Klassen Antwort und Frage – Aditzu

+0

Beide gleichzeitig zu verwenden, hat nichts für mich getan. @ JsonManagedReference/BackReference scheint @JsonIdentityInfo zu überschreiben. –

1

können Sie verwenden @ JsonBackReference/@ JsonManagedReference und diese Methode Kind

@JsonProperty 
public Long getParentId() { 
    return parent == null ? null : parent.getId(); 
} 

Ergebnis sein hinzufügen:

{ 
    "id": 1, 
    "name": "child1", 
    "parentId": 1 
} 

Ich hoffe, das jemand hilft.

Verwandte Themen