我们的产品升级过程包括将旧模式数据库导出到文件(JAXB 序列化),然后导入到新模式(StAX + JAXB)。有时,由于值超出其最大大小导致的插入错误,升级失败,尽管它们先前是从同一个数据库表中导出的。
这发生在反序列化 xml 时(在这种情况下是 Jaxb,但它与 Jaxb 无关)并且其中一个属性具有高代理 UTF-8 字符序列的值,SAX 解析器存在导致输出字符串更大的错误:
3 个字符 -> (1+2+3=) 6 个字符。
6 个字符 -> (1+2+3+4+5+6=) 21 个字符。
(源字符的算术级数)
该代码来自 java 1.7_45 代码类 com.sun.org.apache.xerces.internal.impl.XMLScanner 行:976 - 981:
else if (c != -1 && XMLChar.isHighSurrogate(c)) {
if (scanSurrogates(fStringBuffer3)) {
stringBuffer.append(fStringBuffer3);
if (entityDepth == fEntityDepth && fNeedNonNormalizedValue){
fStringBuffer2.append(fStringBuffer3);
}
循环之间不清除fStringBuffer3缓冲区。
com.sun.org.apache.xerces.internal.impl.XML11DocumentScannerImpl 行中存在类似的代码(相同的方法名称):369 - 375。但是这次在循环期间清除了缓冲区:
else if (c != -1 && XMLChar.isHighSurrogate(c)) {
fStringBuffer3.clear();
if (scanSurrogates(fStringBuffer3)) {
fStringBuffer.append(fStringBuffer3);
if (entityDepth == fEntityDepth) {
fStringBuffer2.append(fStringBuffer3);
}
}
我检查了 java bug 数据库,那里没有提到这个 bug。所以我正在寻找解决这个问题的方法,用 Woodstox 解析器替换 JAXB 解析器解决了这个错误,不幸的是它现在对我们来说太冒险了。
我的代码的一般模式是(返回从文件反序列化的对象的方法的一部分):
XMLInputFactory xmlif = XMLInputFactory.newInstance();
XMLStreamReader xmlStreamReader = xmlif.createXMLStreamReader(new FileReader(file));
try {
while(xmlStreamReader.hasNext()){
boolean skipNext = xmlStreamReader.getEventType() == XMLStreamConstants.START_DOCUMENT;
xmlStreamReader.next();
// If its any other element we are unmarshalling it with JAXB
if((xmlStreamReader.getEventType()== XMLStreamConstants.START_ELEMENT) && !skipNext){
nextElement = innerDeserializer.deserialize();
}
}
}catch (Exception e) {}
有人遇到过这个问题吗?有什么方法可以让我的代码使用第二段代码而不使用 XML 1.1 版?