2012-02-13 29 views
43

Nếu bạn cố gắng sắp xếp một lớp học có sự tham khảo một loại phức tạp mà không có một constructor không có arg, chẳng hạn như:Tại sao JAXB lại cần một hàm tạo arg cho việc sắp xếp lại?

import java.sql.Date; 

@XmlRootElement(name = "Foo") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Foo { 
    int i; 
    Date d; //java.sql.Date does not have a no-arg constructor 
} 

với việc thực hiện JAXB là một phần của Java, như sau:

Foo foo = new Foo(); 
    JAXBContext jc = JAXBContext.newInstance(Foo.class); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    Marshaller marshaller = jc.createMarshaller(); 
    marshaller.marshal(foo, baos); 

JAXB sẽ ném một

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions java.sql.Date does not have a no-arg default constructor 

Bây giờ, tôi hiểu tại sao JAXB cần một không-arg constructor trên unmarshalling - bởi vì nó cần phải nhanh chóng ob ject. Nhưng tại sao JAXB cần một constructor no-arg trong khi marshalling?

Ngoài ra, một nit khác, tại sao việc triển khai JAXB của Java lại ném một ngoại lệ nếu trường đó là null và sẽ không được sắp xếp lại?

Tôi có thiếu thứ gì đó hoặc chỉ là những lựa chọn thực hiện không tốt trong triển khai JAXB của Java không?

+2

Thực thi IMHO thực sự kém của nó. JAXB nên đã làm những gì Jackson làm và đưa ra một chú giải đối số hàm tạo: http://www.cowtowncoder.com/blog/archives/2011/07/entry_457.html. Điều đó đang được nói JAXB vẫn còn tốt hơn nhiều so với các JSR khác. –

Trả lời

22

Khi triển khai JAXB (JSR-222) khởi tạo siêu dữ liệu của nó, đảm bảo rằng nó có thể hỗ trợ cả tính năng đầm lầy và không sửa đổi.

Đối với các lớp học POJO mà không có một constructor không có arg bạn có thể sử dụng một mức độ loại XmlAdapter để xử lý nó:

java.sql.Date không được hỗ trợ theo mặc định (mặc dù trong EclipseLink JAXB (MOXy) nó là). Đây cũng có thể được xử lý bằng cách sử dụng một XmlAdapter định qua @XmlJavaTypeAdapter tại hiện trường, tài sản, hoặc cấp gói:


Ngoài ra, một nit, tại sao Java Việc triển khai JAXB sẽ ném ra một ngoại lệ nếu trường này là rỗng và sẽ không bị marshalled sao?

Bạn đang thấy ngoại lệ gì? Thông thường khi một trường là null, nó không được bao gồm trong kết quả XML, trừ khi nó được chú thích với @XmlElement(nillable=true) trong trường hợp đó phần tử sẽ bao gồm xsi:nil="true".


CẬP NHẬT

Bạn có thể làm như sau:

SqlDateAdapter

Dưới đây là một XmlAdapter rằng sẽ chuyển đổi từ java.sql.Date rằng việc thực hiện JAXB bạn không biết làm thế nào để xử lý một số điện thoại java.util.Date:

package forum9268074; 

import javax.xml.bind.annotation.adapters.*; 

public class SqlDateAdapter extends XmlAdapter<java.util.Date, java.sql.Date> { 

    @Override 
    public java.util.Date marshal(java.sql.Date sqlDate) throws Exception { 
     if(null == sqlDate) { 
      return null; 
     } 
     return new java.util.Date(sqlDate.getTime()); 
    } 

    @Override 
    public java.sql.Date unmarshal(java.util.Date utilDate) throws Exception { 
     if(null == utilDate) { 
      return null; 
     } 
     return new java.sql.Date(utilDate.getTime()); 
    } 

} 

Foo

Các XmlAdapter được đăng ký thông qua @XmlJavaTypeAdapter chú thích:

package forum9268074; 

import java.sql.Date; 
import javax.xml.bind.annotation.*; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlRootElement(name = "Foo") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Foo { 
    int i; 

    @XmlJavaTypeAdapter(SqlDateAdapter.class) 
    Date d; //java.sql.Date does not have a no-arg constructor 
} 
+0

Nếu bạn cố gắng sắp xếp lớp mà tôi đã dán vào câu hỏi, nó sẽ ném một ngoại lệ, mặc dù đối tượng Date là null và thậm chí không là một phần của XML. – rouble

+0

Tôi đã cập nhật câu trả lời của mình để bao gồm một 'XmlAdapter' mà bạn có thể sử dụng để xử lý trường' java.sql.Date'. –

+1

Blaise - cảm ơn. Tôi đã sử dụng một bộ điều hợp tương tự. Lưu ý rằng bạn không cần kiểm tra null trong bộ điều hợp. Tôi đã chỉ ra một số điều thú vị về triển khai JAXB của Java, trong đó, nó mong đợi một bộ điều hợp (và ném một ngoại lệ) - ngay cả khi trường là null và nó sẽ không sử dụng bộ điều hợp. Tôi thấy điều đó thật kỳ quặc. – rouble

-2

Một số doanh nghiệp và Dependency Injection khung sử dụng phản ánh Class.newInstance() để tạo một phiên bản mới cho lớp học của bạn. Phương thức này yêu cầu một constructor no-arg công khai để có thể khởi tạo đối tượng.

+3

cảm ơn - Tôi hiểu rằng - Tôi chỉ tò mò muốn biết, ở đâu trong quá trình marshalling là có cần phải tạo ra một trường hợp mới của lớp được marshalled? – rouble

0

Bạn dường như có ấn tượng rằng mã mẫn JAXB sẽ có đường dẫn cụ thể hành động để khởi tạo. nếu có, điều đó sẽ dẫn đến nhiều mã trùng lặp và sẽ là một triển khai kém. tôi sẽ tưởng tượng rằng mã JAXB có một thói quen chung kiểm tra một lớp mô hình lần đầu tiên nó là cần thiết và xác nhận rằng nó tuân theo tất cả các quy ước cần thiết. trong tình huống này, nó thất bại bởi vì một trong những thành viên không có nhà xây dựng no-arg bắt buộc. logic khởi tạo có nhiều khả năng không phải là marshall/unmarshall cụ thể và cũng rất khó có thể đưa đối tượng hiện tại vào tài khoản.

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