【问题标题】:JAXB flatten list of entities when marshalling编组时 JAXB 展平实体列表
【发布时间】:2019-09-04 03:19:24
【问题描述】:

我使用 JPA/Hibernate 作为我的持久性框架,并且我有以下实体层次结构:

@Entity
@Table(name = "node")
@XmlRootElement(name = "nodeMap")
@XmlAccessorType(XmlAccessType.FIELD)
public class NodeMapDTO {

    @XmlElementWrapper(name = "ipAddresses")
    @XmlElement(name = "ipAddress")
    @OneToMany
    @JoinColumn(name = "node_id")
    private List<IPAddressDTO> ipAddresses;

    [...]
}

@Entity
@Table(name = "node_ip_address")
@XmlAccessorType(XmlAccessType.FIELD)
public class IPAddressDTO {

    @Column(name = "ip_address")
    private String ipAddress;

    [...]
}

当我将 NodeMapDTO 转换为 XML 时,我得到以下结果:

<nodeMap>
   <ipAddresses>
      <ipAddress>
         <ipAddress>192.59.233.20</ipAddress>
      </ipAddress>
   </ipAddresses>
</nodeMap>

但我希望它是:

<nodeMap>
   <ipAddresses>
      <ipAddress>192.59.233.20</ipAddress>
   </ipAddresses>
</nodeMap>

不幸的是,我需要让我的 ipAddresses 字段成为 IPAddressDTOs 而不是 Strings 的列表,因为否则我不能使用 @OneToMany 注释(不,我不想使用 @ElementCollection出于性能原因)。

我也想尝试这样做,而不必创建任何额外的包装类。我想如果我为 List&lt;IPAddressDTO&gt; ipAddresses 字段创建一个包装类,我的 Hibernate 注释将不起作用,它只会使代码比它需要的复杂得多。

谢谢大家。

【问题讨论】:

    标签: java hibernate jpa orm jaxb


    【解决方案1】:

    @XmlValue注释字段ipAddress

    这是一个完整的Minimal, Reproducible Example

    import java.util.*;
    import javax.xml.bind.*;
    import javax.xml.bind.annotation.*;
    
    public class Test {
        public static void main(String[] args) throws Exception {
            Marshaller marshaller = JAXBContext.newInstance(NodeMapDTO.class).createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(new NodeMapDTO(new IPAddressDTO("192.59.233.20")), System.out);
        }
    }
    
    @XmlRootElement(name = "nodeMap")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class NodeMapDTO {
        @XmlElementWrapper(name = "ipAddresses")
        @XmlElement(name = "ipAddress")
        private List<IPAddressDTO> ipAddresses;
    
        NodeMapDTO() {
        }
        NodeMapDTO(IPAddressDTO... ipAddresses) {
            this.ipAddresses = Arrays.asList(ipAddresses);
        }
    }
    
    @XmlAccessorType(XmlAccessType.FIELD)
    public class IPAddressDTO {
        @XmlValue
        private String ipAddress;
    
        IPAddressDTO() {
        }
        IPAddressDTO(String ipAddress) {
            this.ipAddress = ipAddress;
        }
    }
    

    输出

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <nodeMap>
        <ipAddresses>
            <ipAddress>192.59.233.20</ipAddress>
        </ipAddresses>
    </nodeMap>
    

    【讨论】:

    • 这对我来说非常有效。谢谢!如果其他人好奇,我还必须在 IPAddressDTO.ipAddress 字段的 getter 顶部添加一个 @JsonValue 注释,以使其适用于 JSON。
    猜你喜欢
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 2011-10-15
    • 2011-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多