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

Như tôi đã trình bày trong ví dụ khi tôi loại bỏ các @XmlTransient từ Parent lớp phương pháp getList(), sau xml được marshalled:Làm thế nào để kế thừa và JAXB làm việc cùng nhau?

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

Nhưng khi tôi thêm các @XmlTransient chú thích, như trong ví dụ xml được đăng với chỉ ONE danh sách theo yêu cầu.

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

Vì vậy, xin vui lòng ai đó có thể giải thích cho tôi tại sao nó cần thiết để cung cấp cho @XmlTransient trong Chánh Phương pháp lớp getter? Làm thế nào để thừa kế và JAXB liên quan đến nhau cho các trường hợp này?

Trả lời

6

TẠI SAO NÓ xảy ra

Một thực hiện JAXB (JSR-222) sẽ vạch mọi đối tượng miền mà nó là nhận thức của một loại phức tạp. Điều này có nghĩa là nó tin rằng loại XML sau tồn tại cho lớp Parent (khi list không phải là @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> 

Bây giờ Child2 cũng có loại phức tạp. Có hai điều mà JAXB có thể thực hiện:

  • Không cho phép ghi đè thuộc tính, điều này sẽ bị hạn chế.
  • Tạo bản đồ bổ sung cho thuộc tính bị ghi đè. Trong giản đồ bên dưới loại child2, hãy mở rộng parent. Điều này có nghĩa là nó lấy tất cả các phần tử từ loại parent cộng với phần tử riêng của nó.
<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> 

cách sửa chữa nó

Bạn có thể đặt @XmlTransient trên list tài sản trong lớp Parent, nhưng thay vào đó tôi sẽ khuyên bạn nên chú thích lớp Parent với @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); 

} 

Điều này sẽ loại bỏ nó như là một lớp ánh xạ và các loại phức tạp tương ứng với Child2 sẽ trở thành:

<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

Nhưng nếu bạn đang thiết kế một API công cộng? Có cách nào để cung cấp một bộ chú thích mặc định và khiến chúng có thể ghi đè không? Tôi nhận được ấn tượng rằng không có cách nào để làm điều này, tôi có đúng không? xem: http://stackoverflow.com/questions/38348083/jaxb-override-xmlelement-type-of-list – bvdb

Các vấn đề liên quan