Наш процесс обновления продукта включает в себя экспорт старой схемы DB в файлы (сериализация 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-ошибок, эта ошибка здесь не упоминается. Поэтому я ищу исправление для этой проблемы, заменив парсер JAXB парсером Woodstox, решает проблему, к сожалению, это слишком рискованно для нас прямо сейчас.
Общая модель моего кода (часть метода, который возвращает объект, который был десериализован из файла):
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?
Если ошибка содержится в синтаксическом анализаторе SAX, который по умолчанию используется для реализации XML-справки, эталонная реализация JAXB. Вы можете создать StAX XMLStreamReader
на входе и JAXB отменить его.