利用JAXB可以实现XML与Java对象之间的转换。在转换时,可能会遇到交叉引用的情况,如果不做处理,提示为:
A cycle is detected in the object graph. This will cause infinitely deep XML:...
解决办法有两种:利用com.sun.xml.bind.CycleRecoverable和org.eclipse.persistence.oxm.annotations.XmlInverseReference。
以一个Student和SClass类为例。它们之间如果建立双向关系时会引起交叉引用。未处理前代码如下:
public class Student{ private String num; private String name; private SClass sclass; public Student(){ super(); } public Student(String num,String name){ super(); this.num = num; this.name = name; } public SClass getSclass() { return sclass; } public void setSclass(SClass sclass) { this.sclass = sclass; } public String getNum(){ return num; } public void setNum(String num){ this.num = num; } public String getName(){ return name; } public void setName(String name){ this.name = name; } }
@XmlRootElement public class SClass{ private String cnum; private List<Student> students; public SClass(){ super(); } public SClass(String cnum,List<Student> students){ super(); this.cnum = cnum; this.students = students; } public void addStudent(Student student){ if(!this.students.contains(student)){ student.setSclass(this); this.students.add(student); } } public String getCnum(){ return cnum; } public void setCnum(String cnum){ this.cnum = cnum; } public List<Student> getStudents(){ return students; } public void setStudents(List<Student> students){ this.students = students; } }
1.利用com.sun.xml.bind.CycleRecoverable。
需要让两个类都实现接口CycleRecoverable的方法onCycleDetected。以Student为例:
public class Student implements CycleRecoverable{ private String num; private String name; private SClass sclass; ...... public Object onCycleDetected(Context arg0) { // TODO Auto-generated method stub Student student=new Student(); student.setNum(this.getNum()); return student; } }当遇到循环交叉引用时,JAXB引擎会调用该方法,用return的对象来替换this。这样就可以将引起循环引用问题的关系断开,返回给JAXB。
这种方法中,如果是使用maven,需加入依赖:
<dependency> <groupId>javax.xml</groupId> <artifactId>jaxb-impl</artifactId> <version>2.1</version> </dependency>
2. 利用 org.eclipse.persistence.oxm.annotations.XmlInverseReference。
该方法中,要被引用的部分使用@XmlInverseReference标注。本文例中需要在Student部分加入:
SClass: private List<Student> students; Student: @XmlInverseReference(mappedBy="students") private SClass sclass;注意:mappedBy是必须有的属性,其值为引用Student的SClass类的对应field。
特别要注意的是,使用XmlInverseReference时,需要在数据模型类(本例中是Student和SClass)所在package下加入一个jaxb.properties属性文件,里面内容是:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory这种方法中,如果是使用maven,需加入依赖:
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.moxy</artifactId> <version>2.5.0</version> </dependency>