从Java中的结果集中检索存储为二进制XML的oracle XMLType

时间:2013-08-29 18:34:19

标签: java sql oracle hibernate xmltype

如果XMLType列存储为CLOB,我概述了为Oracle 11g(特别是11.2.0.1)编写/读取Oracle XMLType列的解决方案,这是11.2.0.1的默认值。

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

在SQLDeveloper中,如果您在表定义(表DDL)中查看SQL选项卡,它会在11.2.0.1中定义XML列存储,如下所示:

 XMLTYPE COLUMN "ATTRIBUTE_XML2" STORE AS BASICFILE CLOB 

问题: 在Oracle 11.2.0.2中,XMLType的默认存储类型是二进制XML,出于性能原因,它是首选。它看起来像这样:

XMLTYPE COLUMN "ATTRIBUTE_XML2" STORE AS SECUREFILE BINARY XML

但是,一旦以这种方式存储,我引用的解决方案就不再适用于从数据库中读取XMLType列作为XML。它从xmlType.getStringVal()返回一些垃圾,我假设它是oracle二进制编码的XML。

终极问题 我无法从oracle binxml格式转换回有效的XML文档。

我在various configurations as outlined by Oracle尝试了Oracle BinXMLProcessor,BinXMLStream,BinXMLDecoder和InfosetReader,但它们似乎只是读取而不是解码它 - 所以它出错了。

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.getBlobVal(178),xmlType.getBytesValue()替换xmlType.getInputStream(),但它们都抛出异常或返回垃圾数据。

1 个答案:

答案 0 :(得分:0)

找到了捕获,它与代码无关。

Hibernate UserType中正确的nullSafeGet,如引用的答案中所述:

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)时,

问题:必须使用xdb * .jar的最新(11.2.0.2+)分发版,在本例中为xdb6。罐子(~257kb)。较早的xdb * .jar(10.x的〜136kb)仍然可以运行,即使在错误地解码BINARY XML时也不会抛出任何异常。

TL; DR Download xdb6.jar (~257kb) from the Oracle 11gR2 (11.2.0.3) JDBC drivers page。较旧的xdb jar无声地失败,会让你难过。