JAXB如何将复合键字段映射为实体的同级元素?
当然可以做到!你现在遇到的问题是JAXB默认会把@EmbeddedId字段渲染成一个嵌套的<id>元素,要把ChildId里的字段拉到和Child的其他字段同级,这里有两种实用的方案:
方案一:代理嵌入ID的字段(推荐,不改动ChildId结构)
这种方法不需要修改ChildId类的代码,只需要在Child类中为ChildId的每个字段添加代理方法,并通过JAXB注解让这些方法直接映射到XML的同级节点。同时我们要隐藏原来的id字段,避免它被JAXB渲染出来。
修改后的Child类代码如下:
@Entity @Table(name = "CHILD") @XmlRootElement(name = "child") @XmlAccessorType(XmlAccessType.PROPERTY) // 指定基于属性方法进行JAXB映射 public class Child implements java.io.Serializable { @EmbeddedId @XmlTransient // 隐藏默认的id字段映射,避免生成<id>元素 private ChildId id; private String childName; // 注:你原来的代码里这里写的是Date,应该是笔误,改成String更合理 // 代理ChildId的childBirthDate字段,映射为同级的<childBirthDate>元素 @XmlElement(name = "childBirthDate") public Date getChildBirthDate() { return id != null ? id.getChildBirthDate() : null; } public void setChildBirthDate(Date childBirthDate) { if (id == null) { id = new ChildId(); } id.setChildBirthDate(childBirthDate); } // 代理ChildId的childOrder字段,映射为同级的<childOrder>元素 @XmlElement(name = "childOrder") public int getChildOrder() { return id != null ? id.getChildOrder() : 0; } public void setChildOrder(int childOrder) { if (id == null) { id = new ChildId(); } id.setChildOrder(childOrder); } // 原有的childName属性映射 @XmlElement(name = "childName") public String getChildName() { return childName; } public void setChildName(String childName) { this.childName = childName; } // 保留JPA需要的id字段getter/setter,不添加JAXB注解 public ChildId getId() { return id; } public void setId(ChildId id) { this.id = id; } }
这样调整后,JAXB编组时就会把childBirthDate和childOrder直接放在<child>节点下,和childName同级,完全符合你期望的XML格式。
方案二:调整ChildId的JAXB注解(适合允许修改嵌入类的场景)
如果你允许修改ChildId类的代码,可以通过注解让它的字段直接展开到父类的XML层级中:
- 首先修改ChildId类,添加
@XmlAccessorType(XmlAccessType.FIELD)并指定属性顺序:
@Embeddable @XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = {"childBirthDate", "childOrder"}) public class ChildId implements java.io.Serializable { @XmlTransient private Person parentId; // 保持@XmlTransient避免序列化 private Date childBirthDate; private int childOrder; // 原有的getter/setter方法 }
- 接着修改Child类,将
id字段标记为@XmlTransient,并为ChildId的字段添加代理方法(逻辑和方案一一致)。这种方式本质和方案一类似,但通过调整ChildId的注解让结构更清晰,适合可以修改嵌入类的场景。
两种方案都能实现你想要的XML结构,其中方案一因为不需要修改ChildId的结构,更适合已经在JPA中稳定使用的场景。
内容的提问来源于stack exchange,提问作者plugnplay
相关产品推荐
相关产品推荐

