2012-12-18 27 views
10
public abstract class Parent<T> { 
    protected List<T> list; 

    @XmlTransient //Question why do we have to give this here? 
    public abstract List<T> getList(); 
    public abstract void setList(List<T> list); 
} 

@XmlRootElement(name = "child1") 
class Child1 extends Parent<ExtendedElement1>{ 
    @Override 
    public void setList(List<ExtendedElement1> list){ 
     this.list = list; 
    } 

    @Override 
    @XmlElementWrapper(name = "child1-list") 
    @XmlElement(name = "child-list-element") 
    public List<ExtendedElement1> getList(){ 
     return this.list; 
    } 
} 

@XmlRootElement(name = "child2") 
class Child2 extends Parent<ExtendedElement2>{ 
    @Override 
    public void setList(List<ExtendedElement2> list){ 
     this.list = list; 
    } 

    @Override 
    @XmlElementWrapper(name = "child1-list") 
    @XmlElement(name = "child-list-element") 
    public List<ExtendedElement2> getList(){ 
     return this.list; 
    } 
} 


class Element{ 
    @XmlElement(name = "integer", type = int.class) 
    private int i = 2; 
} 

class ExtendedElement1 extends Element{ 
    @XmlElement(name = "extended-element1-str", type = String.class) 
    private String str = "hello"; 
} 

class ExtendedElement2 extends Element{ 
    @XmlElement(name = "extended-element2-str", type = String.class) 
    private String str1 = "hello_there"; 
} 

Jak już pokazano na przykład gdy usunąć z @XmlTransient z Parent klasy getList() metodzie następujące xml jest alarmuje:Jak działa Dziedziczenie i JAXB?

<child1> 
<!-- List is serialized 2 times --> 
    <list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="extendedElement1"> 
     <integer>2</integer> 
     <extended-element1-str>hello</extended-element1-str> 
    </list> 
    <list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="extendedElement1"> 
     <integer>2</integer> 
     <extended-element1-str>hello</extended-element1-str> 
    </list> 
    <list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="extendedElement1"> 
     <integer>2</integer> 
     <extended-element1-str>hello</extended-element1-str> 
    </list> 
    <child1-list> 
     <child-list-element> 
      <integer>2</integer> 
      <extended-element1-str>hello</extended-element1-str> 
     </child-list-element> 
     <child-list-element> 
      <integer>2</integer> 
      <extended-element1-str>hello</extended-element1-str> 
     </child-list-element> 
     <child-list-element> 
      <integer>2</integer> 
      <extended-element1-str>hello</extended-element1-str> 
     </child-list-element> 
    </child1-list> 
</child1> 

Ale kiedy I dodać z @XmlTransient adnotacji, tak jak w przykład xml jest serializowany tylko z wymaganą listą ONE.

<child1> 
    <child1-list> 
     <child-list-element> 
      <integer>2</integer> 
      <extended-element1-str>hello</extended-element1-str> 
     </child-list-element> 
     <child-list-element> 
      <integer>2</integer> 
      <extended-element1-str>hello</extended-element1-str> 
     </child-list-element> 
     <child-list-element> 
      <integer>2</integer> 
      <extended-element1-str>hello</extended-element1-str> 
     </child-list-element> 
    </child1-list> 
</child1> 

więc proszę może ktoś mi wyjaśnić, dlaczego jest to konieczne, aby dać @XmlTransient w Dominującą metodą Klasa pochłaniacza? W jaki sposób dziedziczenie i JAXB odnoszą się do tych przypadków?

Odpowiedz

6

dlaczego jej dzieje

Implementacja JAXB (JSR-222) będzie mapować każdy obiekt domeny, która jest świadoma do typu złożonego. Oznacza to, że uważa, że ​​dla klasy Parent istnieje następujący typ XML (gdy list nie jest @XmlTransient).

<xs:complexType name="parent" abstract="true"> 
    <xs:sequence> 
     <xs:element name="list" type="xs:anyType" nillable="true" minOccurs="0" maxOccurs="unbounded"/> 
    </xs:sequence> 
    </xs:complexType> 

Teraz Child2 również ma typ złożony. Są dwie rzeczy, które mógł wykonać JAXB:

  • Nie pozwalają na nadpisanie właściwości, co byłoby dość ograniczone.
  • Generowanie dodatkowego odwzorowania dla przesłanianej właściwości. W schemacie poniżej typ child2 rozszerza się o parent. Oznacza to, że pobiera wszystkie elementy z rodzaju parent oraz własne.
<xs:complexType name="child2"> 
    <xs:complexContent> 
     <xs:extension base="parent"> 
     <xs:sequence> 
      <xs:element name="child1-list" minOccurs="0"> 
      <xs:complexType> 
       <xs:sequence> 
       <xs:element name="child-list-element" type="extendedElement2" minOccurs="0" maxOccurs="unbounded"/> 
       </xs:sequence> 
      </xs:complexType> 
      </xs:element> 
     </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 

jak to naprawić

Można umieścić @XmlTransient na nieruchomości w klasie Parentlist, ale zamiast Polecam adnotacji klasę Parent z @XmlTransient.

import java.util.List; 
import javax.xml.bind.annotation.XmlTransient; 

@XmlTransient 
public abstract class Parent<T> { 
    protected List<T> list; 

    public abstract List<T> getList(); 
    public abstract void setList(List<T> list); 

} 

To usunie go jako odwzorowanym klasy i typu złożonego, który odpowiada Child2 staną:

<xs:complexType name="child2"> 
    <xs:sequence> 
     <xs:element name="child1-list" minOccurs="0"> 
     <xs:complexType> 
      <xs:sequence> 
      <xs:element name="child-list-element" type="extendedElement2" minOccurs="0" maxOccurs="unbounded"/> 
      </xs:sequence> 
     </xs:complexType> 
     </xs:element> 
    </xs:sequence> 
    </xs:complexType> 
+0

Ale co jeśli projektowania publicznego API? Czy istnieje sposób na zapewnienie domyślnego zestawu adnotacji i sprawienie, by były zastępowalne? Mam wrażenie, że nie ma po prostu sposobu, aby to zrobić, czy mam rację? zobacz: http://stackoverflow.com/questions/38348083/jaxb-override-xmlelement-type-of-list – bvdb