Получение оракула XMLType, хранящегося в виде двоичного XML, из набора результатов в Java
Я изложил решение для записи / чтения в столбец Oracle XMLType для Oracle 11g (в частности, 11.2.0.1), если столбец XMLType хранится как CLOB, что является значением по умолчанию для 11.2.0.1.
ССЫЛКА ОТВЕТА: Использование oracle XMLType в сценарии спящего режима Java Spring
В SQLDeveloper, если вы просматриваете вкладку SQL в определении таблицы (таблица DDL), она определяет хранение столбцов XML в 11.2.0.1 следующим образом:
XMLTYPE COLUMN "ATTRIBUTE_XML2" STORE AS BASICFILE CLOB
Проблема: в Oracle 11.2.0.2 типом хранения по умолчанию для XMLType является Binary XML, который является предпочтительным по соображениям производительности. Это выглядит так:
XMLTYPE COLUMN "ATTRIBUTE_XML2" STORE AS SECUREFILE BINARY XML
ОДНАКО, когда-то сохраненный таким образом, мое решение, на которое ссылаются, больше не работает для ЧТЕНИЯ столбца XMLType как XML из базы данных. Он возвращает некоторый мусор из xmlType.getStringVal(), который, как я полагаю, является двоичным закодированным XML оракулом.
Основная проблема Я не могу преобразовать обратно из формата оракула binxml в действительный документ XML.
Я пробовал Oracle BinXMLProcessor, BinXMLStream, BinXMLDecoder и InfosetReader в различных конфигурациях, как указано в Oracle, но они, похоже, просто читают, а не декодируют его, поэтому он выдает ошибки.
Базовый пример в nullSafeGet (см. Связанный ответ для контекста).
xmlType = (XMLType) rs.getObject(names[0]);
BinXMLProcessor xp = BinXMLProcessorFactory.createProcessor();
BinXMLStream bstr = xp.createBinXMLStream(xmlType.getInputStream());
BinXMLDecoder xdecode = bstr.getDecoder();
InfosetReader reader = xdecode.getReader();
while (reader.hasNext() && i < 25) {
i++;
reader.next();
logger.debug("1 v:" + reader.getValue() + ", s:" + reader.getStandalone() + ", type: " + reader.getEventType() + ", " + reader.getDataLength());
}
Я попробовал похожие подходы, заменив xmlType.getInputStream() на xmlType.getBlobVal(178), xmlType.getBytesValue(), но все они выдают исключение или возвращают данные мусора.
Да.
1 ответ
Нашел подвох, и это не имеет отношения к коду.
Правильный nullSafeGet в Hibernate UserType, как отмечено в указанном ответе:
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
if (logger.isTraceEnabled()) {
logger.trace(" nullSafeSet: " + value + ", ps: " + st + ", index: " + index);
}
try {
XMLType xmlType = null;
if (value != null) {
xmlType = XMLType.createXML(getOracleConnection(st.getConnection()), (String)value);
}
st.setObject(index, xmlType);
} catch (Exception e) {
throw new SQLException("Could not convert String to XML for storage: " + (String)value);
}
}
ПРОБЛЕМА: при использовании столбца SECUREFILE BINARY XML (не CLOB) вы должны использовать самый последний (11.2.0.2+) дистрибутив xdb*.jar, который в данном случае является xdb6.jar (~257kb). Более ранняя версия xdb*.jar (~136 Кбайт для 10.x) будет по-прежнему функционировать без каких-либо исключений даже при неправильном декодировании BINARY XML.
TL; DR: Загрузите xdb6.jar (~ 257 КБ) со страницы драйверов JDBC для Oracle 11gR2 (11.2.0.3). Старые xdb баночки молча терпят неудачу и огорчают вас.