咨询@XmlID与@XmlIDREF协同机制及Publication类引用实现方式
搞懂@XmlID和@XmlIDREF的协同工作,以及你的场景该怎么处理
我来帮你把这两个注解的逻辑理清楚,还有你提到的创建Publication引用的问题~
核心作用拆解
首先得明确这两个注解各自的职责:
- @XmlID:它的作用是给某个Java类标记一个唯一标识符,就像数据库表的主键。注意哦,这个注解只能标注在
String类型的字段/属性上。当JAXB处理这个类的实例时,会把这个字段的值当成该对象在XML中的唯一ID,供其他对象引用。 - @XmlIDREF:这个注解是标记某个字段/属性是对另一个对象的引用,而不是对象本身。序列化XML时,它不会把整个被引用对象的内容嵌进去,只会写出被引用对象的
@XmlID值;反序列化时,JAXB会根据这个ID找到对应的对象实例,而不是重新创建一个新对象。
两者协同工作的流程
举个你的场景例子:
- 序列化阶段:当你序列化Author对象时,JAXB看到
publications字段标注了@XmlIDREF,就会去每个Publication实例里找被@XmlID标注的字段,把那个字段的值作为引用写入XML,而不是把整个Publication的内容都塞进去。 - 反序列化阶段:JAXB会先解析所有带有
@XmlID的对象(比如所有Publication实例),把它们存在一个内部的映射表(ID→对象)里。然后遇到Author的publications引用时,就从映射表里取出对应ID的Publication对象,赋值给列表。
你的关键问题:仅用@XmlIDREF标注publications列表够吗?
答案是不够!你必须在Publication类里也用@XmlID标注一个唯一标识字段,不然JAXB根本不知道该用哪个值作为引用的目标ID,序列化会直接报错,反序列化也找不到对应的对象。
补全你的代码示例
比如给Publication类加上@XmlID:
public class Publication { private String pubId; // 作为唯一标识的字段 private String title; // 其他属性省略 // 必须给这个字段加@XmlID,且类型是String @XmlID @XmlElement public String getPubId() { return pubId; } public void setPubId(String pubId) { this.pubId = pubId; } // 其他getter/setter @XmlElement public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
而你的Author类里,publications字段用@XmlIDREF是没问题的,但要注意:如果没有其他对象需要引用Author,那Author的id字段不需要加@XmlID,它只是Author自己的普通属性而已。
序列化后的XML示例
假设你有一个包含所有Publication和Author的根对象,序列化后会是这样(引用关系清晰,避免重复内容):
<root> <!-- 先定义所有Publication实例,它们的pubId是@XmlID标记的 --> <publications> <publication> <pubId>P1</pubId> <title>Java 核心技术</title> </publication> <publication> <pubId>P2</pubId> <title>JAXB 实战指南</title> </publication> </publications> <!-- Author里的publications只存引用ID --> <author> <id>A1</id> <name>张三</name> <publications>P1</publications> <publications>P2</publications> </author> </root>
总结
@XmlID是给被引用对象(比如Publication)标记唯一ID,必须是String类型。@XmlIDREF是给引用方(比如Author的publications列表)标记,告诉JAXB这里是引用而非对象本身。- 两者必须配合使用,缺一不可,否则无法正确处理对象引用关系。
内容的提问来源于stack exchange,提问作者Jenew
相关产品推荐
相关产品推荐

