必须用getobject()强转xmltype再调getstringvalue(),或改用getcharacterstream()流式读取避免截断;mybatis需自定义typehandler,注意jar包版本对齐。

Oracle JDBC驱动不支持直接获取XMLType为String
Java通过JDBC从Oracle查出XMLType字段时,ResultSet.getString()会抛SQLException: Invalid column type。这不是代码写错了,而是Oracle官方JDBC驱动(尤其是12c及以前版本)默认把XMLType映射为oracle.xdb.XMLType对象,而非基础类型。
必须显式调用getObject()并强转为oracle.xdb.XMLType,再用其getStringValue()或getDOM()提取内容。
- 确保classpath中有
xmlparserv2.jar(12c前)或ojdbc8.jar+xmlparserv2.jar(12c+),否则XMLType类加载失败 - 若用Spring JDBC,
JdbcTemplate.queryForObject()需配合new SqlReturnType() { ... }手动处理,不能依赖默认类型转换 - 19c+驱动中可尝试设置JDBC连接参数
oracle.jdbc.xmlType=STRING,但仅对部分简单XML生效,含命名空间或CDATA时仍可能失败
XMLType.getStringValue()可能截断超长内容
XMLType.getStringValue()底层调用Oracle的getClobVal().toString(),而CLOB在JDBC中受oracle.jdbc.defaultRowPrefetch和驱动内部缓冲区限制,单次读取可能只返回前4000字符——尤其当XML含大量文本节点时,后半部分直接丢失。
更可靠的做法是先用getClobVal()拿到CLOB对象,再用getCharacterStream()流式读取:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
XMLType xml = (XMLType) rs.getObject("xml_col");
if (xml != null) {
Reader reader = xml.getCharacterStream(); // 不会截断
String xmlStr = new BufferedReader(reader).lines()
.collect(Collectors.joining("\n"));
}
- 避免用
xml.getStringValue().length()做长度校验——它返回的是被截断后的长度 - 若XML含二进制Base64数据,优先用
getBlobVal()转BLOB再解码,getStringValue()会破坏编码
DOM解析时namespace和encoding容易出错
直接用xml.getDOM()返回的Document对象,常出现org.w3c.dom.DOMException: INVALID_CHARACTER_ERR或中文乱码,根源是Oracle返回的DOM未正确声明encoding,且默认关闭namespace支持。
安全做法是弃用getDOM(),改用字符串流重新解析:
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = builder.parse(new InputSource(xml.getCharacterStream()));
- 必须调用
setNamespaceAware(true)在DocumentBuilderFactory上,否则带xmlns的XML节点无法用XPath定位 - 不要依赖
xml.getStringValue()构造InputSource,它可能已损坏BOM或编码声明;getCharacterStream()能保持原始字节流语义 - 若XML声明了
encoding="GBK",需在InputSource上显式设setEncoding("GBK"),否则JDK默认按UTF-8解码
MyBatis里XMLType字段需要自定义TypeHandler
MyBatis默认不识别XMLType,直接在resultMap里写java.lang.String会报ResultMapException: Error attempting to get column 'xml_col' from result set。
必须实现TypeHandler<string></string>,并在configuration.xml或注解中注册:
public class XMLTypeHandler implements TypeHandler<string> {
@Override
public String getResult(ResultSet rs, String columnName) throws SQLException {
XMLType xml = (XMLType) rs.getObject(columnName);
return xml == null ? null : xml.getStringValue();
}
// ... 其他方法需实现,注意setParameter要new XMLType(conn, str)
}
</string>
- 注意
setParameter方法里创建XMLType需传入当前Connection,否则插入时报ORA-01001: invalid cursor - Spring Boot用户可在
@MapperScan所在配置类中用@Bean注册该handler,并通过@ConfigurationProperties("mybatis.type-handlers-package")自动扫描 - 若项目同时用Hibernate,别混淆——Hibernate需用
@Lob+ 自定义UserType,和MyBatis方案不兼容
XMLType就会变成null或ClassCastException。Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










