我已经实现了基于JPA和JAXB的REST API。
我的课程大致相同(非常简化):
@Entity
@XmlRootElement
...
public class Thing {
@Id
@GeneratedValue
...
@XmlAttribute
@XmlID
@XmlJavaTypeAdapter(JAXBLongAdapter.class)
private Long id;
...
}
Hibernate(我当前的JPA提供程序)生成数字作为id值,但它们自然只对于一种类型是唯一的,在本例中为Thing。
现在XSD说xsd:id(@XmlID)是一个NCString,它不能是普通数字,所以我在前面添加了一个' _'到JAXBLongAdapter中的数字。 - 喜欢' _1'
现在架构验证器抱怨:
[org.xml.sax.SAXParseException: cvc-id.2: There are multiple occurrences of ID value '_1'.]
如果我理解正确,xsd:ID元素必须具有xml文档中全局唯一的(字符串)值。但这与在数据库中使用ID的常见方式截然相反。
我现在该怎么办? 我想到了三件事:
似乎我现在必须更改数据库架构以使用不同的ID。 - 但如果ID仍然很短,那将会很好,因为它们出现在URL中。
我的问题:是否存在速度相对较快并且全球唯一的ID生成器? 还是有另一种解决方法吗?
编辑:
这种黑客有点工作,保留了JPA ID。
@XmlID
@XmlAttribute(name="id")
private String getXmlID(){
return String.format("%s-%s", this.getClass().getSimpleName(), this.getId().toString());
}
private void setXmlID(String xmlid){
String prefix = String.format("%s-", this.getClass().getSimpleName());
if(xmlid.startsWith(prefix)){
this.id = Long.parseLong(xmlid.substring(prefix.length()));
}else{
throw new IllegalArgumentException(xmlid+" does not look like "+prefix+"###");
}
}
将JAXB Annotation从字段移动到XmlID的专用私有getter / setter。
答案 0 :(得分:2)
这正是我一段时间所做的事情。
编组时,您可以问自己这个域对象的实际@XmlID
是什么?
我曾经认为@XmlID
和@XmlIDREF
可以解决JAXB中的循环问题。
以下是我对JPA实体以及JAXB注释所做的事情。
不要放弃simple JPA @Id
。这是JPA的核心。
@XmlRootElement
public class Parent {
@Id
@XmlAttribute
private Long id;
@OneToMany
@XmlElement(name = "child")
@XmlElementWrapper
private Collection<Child> children;
}
@XmlRootElement
public class Child {
@XmlAttribute
private Long getParentId() {
return parent.getId();
}
@Id
@XmlAttribute
private Long id;
@ManyToOne
@XmlTransient // for preventing infinite circular problem
private Parent parent;
}
答案 1 :(得分:2)
注意:我是EclipseLink JAXB (MOXy)主管,是JAXB (JSR-222)专家组的成员。
答案应该
答案应该是在@XmlSchemaType
和@XmlID
属性上使用@XmlIDREF
注释。不幸的是,JAXB RI没有利用这种组合,而EclipseLink MOXy仅将其用于@XmlID
。我输入了以下MOXy错误,如果您对此方法感兴趣,我们可以修复:
<强>员工强>
package forum11791735;
import java.util.List;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {
@XmlID
@XmlJavaTypeAdapter(JAXBLongAdapter.class)
@XmlSchemaType(name="long")
private Long id;
@XmlIDREF
@XmlSchemaType(name="long")
private Employee manager;
@XmlElement(name="report")
private List<Employee> reports;
}
周围工作
您看到的错误似乎是由于架构验证。您是否可以禁用架构验证或在ValidationEventHandler
上设置Unmarshaller
以忽略这些错误?
<强>替代物强>
如果您使用@XmlID
/ @XmlIDREF
来映射双向关系,那么您可能对MOXy的@XmlInverseReference
扩展程序感兴趣: