我已经实现了一个基于 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 的常见方式完全相反。
现在我该怎么做?我想到了三件事:
- 为具有特定类型前缀的每种类型创建一个 JAXBLongAdapter?
- 使用另一个 JPA id 生成器,也许是 UUID?- 但是哪一个?
- 停止使用@XmlID 和@XmlIDREF,这会造成冗余和一般混乱。
看来我现在必须更改数据库模式以使用不同的 ID。- 但如果 ID 保持简短就更好了,因为它们出现在 URL 中。
我的问题:是否有一个速度相当快且全球唯一的 ID 生成器?还是有另一种解决方法?
编辑:
这个 hack 有点工作,让 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 注释从字段移动到 XmlID 的专用私有 getter/setter。