2010-06-18 14 views
18

Mam wykres obiektowy, który zawiera cykl. Jak mogę JAXB poradzić sobie z tym? Próbowałem użyć adnotacji @XmlTransient w klasie potomnej, ale koordynator JAXB nadal wykrywa cykl.Odwzorowanie cykliczne JAXB na XML

@Entity 
@XmlRootElement 
public class Contact { 

    @Id 
    private Long contactId; 

    @OneToMany(mappedBy = "contact") 
    private List<ContactAddress> addresses; 

... 

} 

@Entity 
@XmlRootElement 
public class ContactAddress { 

    @Id 
    private Long contactAddressId; 

    @ManyToOne 
    @JoinColumn(name = "contact_id") 
    private Contact contact; 

    private String address; 

... 

} 

Odpowiedz

12

Dobrą rzeczą w stosowaniu JAXB jest to, że jest to standardowy program wykonawczy z wieloma implementacjami (podobnie jak JPA).

Jeśli korzystasz z EclipseLink JAXB (MOXy), masz do dyspozycji wiele rozszerzeń do obsługi jednostek JPA, w tym relacji dwukierunkowych. Odbywa się to za pomocą adnotacji MOXy @XmlInverseReference. Działa on podobnie do @XmlTransient na marshall i wypełnia relację target-to-source na unmarshal.

http://wiki.eclipse.org/EclipseLink/Examples/MOXy/JPA/Relationships

@Entity 
@XmlRootElement 
public class Contact { 

    @Id 
    private Long contactId; 

    @OneToMany(mappedBy = "contact") 
    private List<ContactAddress> addresses; 

... 

} 

@Entity 
@XmlRootElement 
public class ContactAddress { 

    @Id 
    private Long contactAddressId; 

    @ManyToOne 
    @JoinColumn(name = "contact_id") 
    @XmlInverseReference(mappedBy="addresses") 
    private Contact contact; 

    private String address; 

... 

} 

Inne rozszerzenia są dostępne w tym wsparcie dla kluczy kompozytowych & wbudowane kluczowe klas.

Aby określić realizację EcliseLink Moxy JAXB trzeba zawierać jaxb.properties złożyć w swoim klasach modelowych (tj zamówienia) z następującego wpisu:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 
+0

Być może jest to problem JAX-RS. Nadal mam wyjątek mówiąc, że wykryto cykl - javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException - z połączonym wyjątkiem: [com.sun.istack.SAXException2: Wykryto cykl na wykresie obiektu . –

+0

Należy dodać plik jaxb.properties określający środowisko wykonawcze MOXy środowiska EclipseLink. Dodałem instrukcje do powyższej odpowiedzi. –

+0

Działa świetnie. Dzięki. –

17

This page w "Unofficial JAXB Guide" oferuje trzy strategie radzenia sobie z cykli. Są one następujące (podsumowanie):

  • Zaznacz jeden z atrybutów odniesienia, które tworzą cykl jako @XmlTransient.
  • Użyj @XmlID i @XmlIDREF, aby odniesienia były reprezentowane przy użyciu identyfikatorów XML ids niż przez ograniczenie.
  • Użyj interfejsu CycleRecoverable, aby programowo obsługiwać cykle.
+0

XmlID i XmlIDREF są łatwe w użyciu. Dodaj adnotację XmlID do metody public String getId() {return Integer.toString (System.identityHashCode (this)); } i otrzymujesz prosty sposób przypisania unikalnych identyfikatorów do elementów XML. – astraujums

6

XMLTransient prawie zawsze pracuje dla cykli. Być może istnieje możliwość, że masz XMLTransient na poziomie pola, ale nie określiłeś XMLAccessorType jako XmlAccessType.Field. Jeśli nic nie podasz, domyślnie jest to XmlAccessType.Property - lub twoje pobierające. Doświadczyłem, że Jaxb wybiera elementy xml z getter z klasy, dla których pominięto adnotacje typu accessor i nadal działa doskonale.

1

Możemy użyć XStream biblioteki, jak również, próbowałem to jeden projekt, gdzie JAXB dawał błąd cykliczny ale XStream obchodzić go pomyślnie

+1

Zwyczajowo pokazuje, w jaki sposób chcesz użyć oprócz podania odniesienia. [Edytuj] odpowiedź na to pytanie. –

Powiązane problemy