为什么以及何时在JAXB中需要JAXBElement?

时间:2013-12-05 09:39:17

标签: java xml oracle jaxb xsd

我刚刚学习JAXB(用于XML绑定的Java体系结构)。通过一些消息来源,我想到了JAXBElement的一个疑问。

Oracle文档说:

When XML element information can not be inferred by the derived Java representation of the XML content, a JAXBElement object is provided. This object has methods for getting and setting the object name and object value. Link here

当Schema定义的数据类型与Java数据类型之间没有直接映射时,是否需要使用JAXBElement

此外,在下面列出的一个代码示例中。我跟随here

 ObjectFactory factory = new ObjectFactory();

    UserT user = factory.createUserT();
    user.setUserName("Sanaulla");
    ItemT item = factory.createItemT();
    item.setItemName("Seagate External HDD");
    item.setPurchasedOn("August 24, 2010");
    item.setAmount(new BigDecimal("6776.5"));

    ItemListT itemList = factory.createItemListT();
    itemList.getItem().add(item);

    ExpenseT expense = factory.createExpenseT();// we get expense object here
    expense.setUser(user);
    expense.setItems(itemList);

    JAXBContext context = JAXBContext.newInstance("generated");
    JAXBElement<ExpenseT> element = factory.createExpenseReport(expense);//why is this required
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE);
    marshaller.marshal(element,System.out);

使用ExpenseT expense = factory.createExpenseT();我们可以获得ExpenseT个对象。

如果我们在代码中再次看到,我们创建了
JAXBElement<ExpenseT> element = factory.createExpenseReport(expense);
根据this source,它是expense对象的包装。
另一方面,我们不为使用UserT user = factory.createUserT();检索的对象创建包装器

所以我的问题是:

  1. 围绕JAXBElement的{​​{1}}包装需要什么?
  2. 何时使用expense

2 个答案:

答案 0 :(得分:9)

有一些用例需要JAXBElement

  1. 元素同时为nillable="true"minOccurs="0"。在这种情况下,映射字段/属性上的null是什么意思?当属性为JAXBElement时,空值表示该元素不存在,而JAXBElement包装null表示带有xsi:nil="true"的XML元素。
  2. 有两个全局元素具有相同的命名复杂类型。由于在JAXB类中对应于复杂类型,因此需要一种方法来捕获遇到的根元素。
  3. 有一个选择结构,其中foobar元素可以出现,它们是相同的类型。这里需要JAXBElement,因为仅仅遇到String值不足以指示应该对哪个元素进行编组。
  4. 在包含属性的文档中遇到包含xsi:nil的元素。在此示例中,对应于该元素的对象仍然可以被解组以保存属性值,但JAXBElement可以指示该元素为null。

答案 1 :(得分:4)

JAXBElement用于在对象模型中不存在足够信息的用例中保留元素名称/命名空间。它经常与替代组一起使用。

如果没有任何JAXB元数据,结果将被包装在JAXBElement中。 您可以使用@XmlRootElement批注来消除根级别JAXBElement。

如果您使用来自外部源的xsd文件,并且在生成的类上没有可用的XmlRootElement注释,则在编组过程中使用JAXBElement可以真正派上用场,因为您可以使用JAXBElement包装器将xml解组为对象。您将看到指定类本身在这种情况下不起作用...

这将有效:

JAXBElement<Object> je = (JAXBElement<Object>) unmarshaller.unmarshal(objectXML);
Object = je.getValue();

这将抛出一个JAXBException:

Object obj = (Object) unmarshaller.unmarshal(objectXML);