Retrieving oracle XMLType stored as binary XML from a resultset in Java

青春壹個敷衍的年華 提交于 2020-01-17 05:26:38

问题


I outlined a solution to writing/reading to an Oracle XMLType column for Oracle 11g (specifically 11.2.0.1) if the XMLType column is stored as a CLOB, which is the default for 11.2.0.1.

REFERENCE ANSWER: Using oracle XMLType in a java spring hibernate scenario

In SQLDeveloper, if you view the SQL tab within a table definition (table DDL) it defines the XML columns storage in 11.2.0.1 like this:

 XMLTYPE COLUMN "ATTRIBUTE_XML2" STORE AS BASICFILE CLOB 

Problem: In Oracle 11.2.0.2, the default storage type for XMLType is Binary XML, which is preferred for performance reasons. It looks like this:

XMLTYPE COLUMN "ATTRIBUTE_XML2" STORE AS SECUREFILE BINARY XML

HOWEVER, once stored this way, my referenced solution no longer works for READING the XMLType column as XML from the database. It returns some garbage from xmlType.getStringVal(), which I assume is the oracle binary encoded XML.

Ultimate Problem I am unable to convert back from the oracle binxml format to a valid XML document.

I have tried the Oracle BinXMLProcessor, BinXMLStream, BinXMLDecoder and InfosetReader in various configurations as outlined by Oracle, but they seem to just read, rather than decode it - so it errors out.

Basic example within the nullSafeGet (see linked answer for context).

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());
}

I tried similar approaches, replacing xmlType.getInputStream() with xmlType.getBlobVal(178), xmlType.getBytesValue(), but they all throw an exception or return garbage data.

Huh.


回答1:


Found the catch, and it's not related to the code.

The proper nullSafeGet in the Hibernate UserType, as noted in the referenced answer is:

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);
    }
}

PROBLEM: when using a SECUREFILE BINARY XML column (not CLOB) you must use the most recent (11.2.0.2+) distribution of the xdb*.jar, which in this case is xdb6.jar (~257kb). The earlier xdb*.jar (~136kb for 10.x) will still function, without tossing any exceptions even when incorrectly decoding BINARY XML.

TL;DR: Download xdb6.jar (~257kb) from the Oracle 11gR2 (11.2.0.3) JDBC drivers page. Older xdb jars fail silently and will make you sad.



来源:https://stackoverflow.com/questions/18518569/retrieving-oracle-xmltype-stored-as-binary-xml-from-a-resultset-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!