java 继承和 JAXB 如何协同工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13928222/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 14:29:02  来源:igfitidea点击:

How do Inheritance and JAXB work together?

javajaxbxml-serialization

提问by Narendra Pathai

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";
}

As I have shown in the example when I removethe @XmlTransientfrom the Parentclass getList()method, following xml is marshalled:

正如我在例如已经显示,当我删除@XmlTransientParentgetList()方法,下面的XML被编组:

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

But when I addthe @XmlTransientannotation, as in the example the xml is serialized with only ONElist as required.

但是,当我@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>

So please can someone explain me why is it required to give @XmlTransientin Parent Class getter method? How does inheritance and JAXB inter-relate for these cases?

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

采纳答案by bdoughan

WHY ITS HAPPENING

为什么会发生

A JAXB (JSR-222)implementation will map every domain object that it is aware of to a complex type. This means it believes that the following XML type exists for the Parentclass (when listis not @XmlTransient).

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

Now Child2also has a complex type. There are two things JAXB could have done:

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

  • Not allow properties to be overridden, which would be pretty limiting.
  • Generate an additional mapping for the overridden property. In the schema below the child2type extends parent. This means it gets all the elements from the parenttype plus its own.
  • 不允许覆盖属性,这将是非常有限的。
  • 为覆盖的属性生成附加映射。在下面的架构中,child2类型 extends 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>

HOW TO FIX IT

如何修复

You could put @XmlTransienton the listproperty in the Parentclass, but instead I would recommend annotating the Parentclass with @XmlTransient.

你可以把@XmlTransient关于list在房地产Parent类,而是我会建议注释的Parent带班@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);

}

This will remove it as a mapped class and the complex type that corresponds to Child2will become:

这会将其作为映射类删除,对应的复杂类型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>