2012-04-05 22 views
12

Używam biblioteki Gson do konwersji obiektów Java na odpowiedź Json ... Problem polega na tym, że po żądaniach JPA obiekt pobrany z DB nie może zostać przekonwertowany z powodu rekurencyjnej relacji z innymi jednostkami (see my previous question), na przykład:Najprostszym sposobem na usunięcie dwukierunkowych relacji rekurencyjnych?

public class Gps implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @Basic(optional = false) 
    @Column(name = "IMEI", nullable = false, length = 20) 
    private String imei; 
    //some code here... 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "gpsImei", fetch = FetchType.LAZY) 
    private List<Coordonnees> coordonneesList; 


public class Coordonnees implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "IDCOORDONNEES", nullable = false) 
    private Integer idcoordonnees; 
    //some code here... 
    @JoinColumn(name = "GPS_IMEI", referencedColumnName = "IMEI", nullable = false) 
    @ManyToOne(optional = false, fetch = FetchType.LAZY) 
    private Gps gpsImei; 

Mój kod źródłowy:

EntityManagerFactory emf=Persistence.createEntityManagerFactory("JavaApplication21PU"); 
    GpsJpaController gjc=new GpsJpaController(emf); 

    Gps gps=gjc.findGps("123456789"); 

    for(int i=0;i<gps.getCoordonneesList().size();i++){ 
    gps.getCoordonneesList().get(i).setGpsImei(null); 
    } 

    Gson gson=new Gson(); 
    String json=gson.toJson(gps);//convert to json response 

    System.out.println(json); 

Jak widać tutaj zrobiłem:

for(int i=0;i<gps.getCoordonneesList().size();i++){ 
    gps.getCoordonneesList().get(i).setGpsImei(null); 
    } 

tylko po to, aby zniszczyć relację rekursywną, ustawiając wartość null dla każdego obiektu GPS w katalogu coordonneesList.

Czy Twoim zdaniem jest to dobre rozwiązanie, czy jest jeszcze inna praktyczna metoda? Dzięki

Odpowiedz

25

Istnieje rozszerzenie Gson o nazwie GraphAdapterBuilder, które może serializować obiekty zawierające odwołania kołowe. Oto bardzo uproszczony przykład z odpowiedniego testu:

Roshambo rock = new Roshambo("ROCK"); 
Roshambo scissors = new Roshambo("SCISSORS"); 
Roshambo paper = new Roshambo("PAPER"); 
rock.beats = scissors; 
scissors.beats = paper; 
paper.beats = rock; 

GsonBuilder gsonBuilder = new GsonBuilder(); 
new GraphAdapterBuilder() 
    .addType(Roshambo.class) 
    .registerOn(gsonBuilder); 
Gson gson = gsonBuilder.create(); 
System.out.println(gson.toJson(rock)); 

Drukuje:

{ 
    '0x1': {'name': 'ROCK', 'beats': '0x2'}, 
    '0x2': {'name': 'SCISSORS', 'beats': '0x3'}, 
    '0x3': {'name': 'PAPER', 'beats': '0x1'} 
} 

Uwaga, że ​​klasa GraphAdapterBuilder jest nie zawarte w gson.jar. Jeśli chcesz go użyć, musisz ręcznie skopiować go do projektu.

+1

Dzięki! To był ratownik podczas pracy ze stanem hibernacji. Zaoszczędził mnóstwa kłopotów przy konwertowaniu elementu hibernacji za pomocą gson. – Knubo

+0

działa również na Androidzie. –

+3

który jar zawiera tę klasę "GraphAdapterBuilder"? – pavan

2

Nie znam się na Gsonie, ale pracuję z Jacksonem. Wyszukaj przykład użycia klasy ObjectMapper. Jeśli chodzi o rekursję, użyj @JsonManagedReference i @JsonBackReference aby to zatrzymać. Zapoznaj się również z nimi na przykład.

1

Możesz użyć @Expose (serialize = false), aby uniknąć serializacji serialu.

0

Użyj opcji przemijający za ignorowanie @OneToMany ustawia dla google.gson

Powiązane problemy