2012-12-18 129 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"; 
} 

正如我在我ParentgetList()方法除去@XmlTransient,下面的XML被编组的例子已经表明:继承和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> 

但是,当我添加@XmlTransient注释,如在xml序列化的例子只需要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> 

所以请有人可以解释我为什么需要它给@XmlTransient在父类的getter方法?继承和JAXB如何相互关联这些情况?

回答

6

为什么事情发生

一个JAXB (JSR-222)实施将映射每个领域对象,它是知道的复杂类型。这意味着它认为Parent类存在以下XML类型(当list不是@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> 

现在Child2也有一个复杂的类型。 JAXB可以做两件事:

  • 不允许属性被覆盖,这是非常有限的。
  • 为重写的属性生成附加映射。在child2类型下面的模式中,延伸parent。这意味着它从parent类型加上它自己的所有元素。
<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> 

如何解决它

你可以把@XmlTransient上的Parent类的list财产,而是我会建议与@XmlTransient注解Parent类。

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); 

} 

这将消除它作为一个映射的类,对应于Child2将成为复杂类型:

<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

但是,如果你在设计一个公共的API是什么?有没有办法提供一组默认的注释,并使它们覆盖?我得到的印象是没有办法做到这一点,我是否正确?请参阅:http://stackoverflow.com/questions/38348083/jaxb-override-xmlelement-type-of-list – bvdb