如何从weblogic.jdbc.wrapper.Clob_oracle_sql_CLOB获取字符串?
遇到这种Weblogic JDBC包装对象的问题确实头疼,结合你的环境(Oracle 11g、Weblogic 9.2、Java 4),给你几个可行的解决方案:
方案1:直接通过Clob接口读取字符串(无需解包)
Weblogic的weblogic.jdbc.wrapper.Clob_oracle_sql_CLOB其实实现了标准的java.sql.Clob接口,不用纠结解包,直接用接口方法读取内容即可。代码示例:
Object valueObj = element.get("VALUE"); String value = null; if (valueObj instanceof Clob) { Clob clob = (Clob) valueObj; // 方式1:直接截取全部内容(注意:若Clob长度超过int最大值会报错,你的场景大概率不会出现) value = clob.getSubString(1, (int) clob.length()); // 方式2:用字符流读取(更适合大内容场景) // BufferedReader reader = new BufferedReader(clob.getCharacterStream()); // StringBuilder sb = new StringBuilder(); // String line; // while ((line = reader.readLine()) != null) { // sb.append(line); // } // reader.close(); // value = sb.toString(); }
这个方案不需要修改SQL,直接处理包装后的对象即可,完全兼容Weblogic的包装机制。
方案2:修改SQL直接返回字符串(最省事)
如果XML节点的内容长度不超过Oracle VARCHAR2的限制(Oracle 11g中是4000字节),可以直接修改SQL,用getStringVal()替代getClobVal(),让数据库直接返回字符串:
SELECT EXTRACT(XML_TEXT, 'PATH/TO/XML/VALUE/text()').getStringVal() AS VALUE FROM MYTBALE WHERE id = xxxx;
这样Java代码里直接把element.get("VALUE")转成String就行,完全不用处理Clob或Opaque对象。如果内容超过4000字节,这个方法就不适用了,得回到方案1。
方案3:处理Opaque对象的情况(不用getClobVal()时)
如果不使用getClobVal()返回oracle.sql.Opaque,这个对象其实是Oracle XMLType的底层存储类型,你可以把它转成XMLType再提取字符串:
Object valueObj = element.get("VALUE"); String value = null; if (valueObj instanceof oracle.sql.Opaque) { oracle.sql.XMLType xmlType = oracle.sql.XMLType.createXML((oracle.sql.Opaque) valueObj); value = xmlType.getStringVal(); }
注意需要确保你的项目类路径里包含Oracle的XMLType相关jar包(Weblogic 9.2通常会自带这个)。
方案4:数据库端用DBMS_LOB处理大内容
如果XML内容超过VARCHAR2限制,又不想在Java里处理Clob,可以在SQL里用DBMS_LOB.SUBSTR分块提取(适合内容长度可控的场景,Java 4处理分块略繁琐):
SELECT DBMS_LOB.SUBSTR( EXTRACT(XML_TEXT, 'PATH/TO/XML/VALUE/text()').getClobVal(), 4000, -- 每次提取的长度 1 -- 起始位置 ) AS VALUE FROM MYTBALE WHERE id = xxxx;
如果内容超过4000字节,需要多次调整起始位置调用,不过这个方法在内容长度不大时也能直接返回字符串。
补充说明
Weblogic的JDBC包装机制是为了连接池和事务管理,既然无法禁用,就不用强行解包,而是利用标准JDBC接口或者Oracle提供的类型转换方法来处理,上面的方案都不需要禁用包装,完全适配你的环境。
内容的提问来源于stack exchange,提问作者tec

