如何将单个java bean编组为具有现有注释的复杂XML文档?

时间:2011-01-26 22:41:53

标签: java xml annotations jaxb

我有一个已经为JPA注释的java bean,我也希望将其存储为XML,特别是FIXML。目标是使用注释管理从bean到XML的映射。

我在网上看到有关指定架构和让JAXB生成类的相关主题,但我不想这样做。

我一直在寻找使用JAXB注释,但似乎我需要为每个子元素创建新类。我试图远离那个,让注释显示如何构建子元素。 JAXB似乎不想这样做。

这可能,怎么样?我是否需要制作自己的注释并忘记JAXB?

具体示例

豆:

@Entity
@XmlRootElement(name="FIXML")
@XmlType(name="ExecRpt")
public class ExecutionReport implements Serializable {
    private String account;
    private String senderCompID;

    @Column(name="ACCOUNT", nullable=true, length=64)
    @XmlAttribute(name="Acct")
    public String getAccount() {
        return this.account;
    }
    public void setAccount(String account) {
        this.account = account;
    }

    @Column(name="SENDER_COMP_ID", nullable=true, length=200)
    @XmlAttribute(name="SID")
    public String getSenderCompID() {
        return this.senderCompID;
    }
    public void setSenderCompID(String senderCompID) {
        this.senderCompID = senderCompID;
    }
}

解析:

JAXBContext context = JAXBContext.newInstance(ExecutionReport.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); //pretty print XML
marshaller.marshal(executionReport, System.out);

所需的XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FIXML>
  <ExecRpt Acct="account_data">
    <Hdr SID="sender"/>
  </ExecRpt>
</FIXML>

当前产生的XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FIXML Acct="account_data" SID="sender"/>

显然,我还没有提供足够的信息来映射子元素,但我也不确定如何提供它。我想添加一些@XmlElement注释,但我没有子对象,所有数据都在这个类中。

好处是我的XML并不比这个例子复杂得多;只有少数元素,每条消息只出现一次。给我带来麻烦的是从单个bean中获取多个元素。

2 个答案:

答案 0 :(得分:4)

您可以在EclipseLink JAXB (MOXy)中使用@XmlPath扩展名,我是技术主管。

模型类

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@Entity
@XmlRootElement(name="FIXML")
@XmlType(name="ExecRpt")
public class ExecutionReport implements Serializable {
    private String account;
    private String senderCompID;

    @Column(name="ACCOUNT", nullable=true, length=64)
    @XmlPath("ExecRpt/@Acct")
    public String getAccount() {
        return this.account;
    }
    public void setAccount(String account) {
        this.account = account;
    }

    @Column(name="SENDER_COMP_ID", nullable=true, length=200)
    @XmlPath("ExecRpt/Hdr/@SID")
    public String getSenderCompID() {
        return this.senderCompID;
    }
    public void setSenderCompID(String senderCompID) {
        this.senderCompID = senderCompID;
    }
}

演示代码

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Demo {

    public static void main(String[] args) throws Exception  {
        JAXBContext jc = JAXBContext.newInstance(ExecutionReport.class);

        ExecutionReport er = new ExecutionReport();
        er.setAccount("account_data");
        er.setSenderCompID("sender");

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(er, System.out);
    }

}

生成的XML

<?xml version="1.0" encoding="UTF-8"?>
<FIXML>
   <ExecRpt Acct="account_data">
      <Hdr SID="sender"/>
   </ExecRpt>
</FIXML>

指定EclipseLink JAXB(MOXy)实现

要将MOXy指定为JAXB实现,您需要使用以下条目在 ExecutionReport 类中添加名为 jaxb.properties 的文件:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

了解更多信息

答案 1 :(得分:1)

我不知道Jaxb注释但是如果你在ExecRpt中要求一个属性,那么在ExecRpt中有一个属性似乎是正常的吗?

我认为你期望这些注释过多。你是否也想要一个带有字符串的注释,用分隔符拆分它并生成一个子元素列表?

在我看来,将这些注释直接放在JPA实体上是一个糟糕的设计。有一天你可能不得不为表现问题做一些数据库更改,例如,你无法生成你想要的xml。为什么不将你的jpa实体转换为jaxb友好的给定结构,以便你保持db和marshalling appart?因此,在改变时你只需要修改变压器。