You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle 1.8 CachedRowSet.populate执行systimestamp查询报错咨询

我之前也碰到过几乎一模一样的问题,咱们来好好捋捋原因和解决办法:

问题根源分析

你遇到的这个java.sql.SQLException: Invalid SQL type for column异常,核心原因是Oracle的systimestamp返回的是TIMESTAMP WITH TIME ZONE类型,而你用的ojdbc6.jar在配合JDK 1.8的RowSet实现时,对这种Oracle特定的时间类型的映射存在兼容性bug。

RowSet.populate()方法在处理ResultSet时,会依赖JDBC驱动返回的SQL类型码来做类型适配,但ojdbc6并没有正确注册TIMESTAMP WITH TIME ZONE对应的JDBC类型,导致RowSet无法识别这个列的类型,直接抛出异常。而其他查询语句(比如查普通DATE类型的sysdate)没问题,就是因为那些类型的映射是完善的。

可行的解决办法

这里有几个经过验证的方案,你可以根据自己的场景选择:

  • 修改查询语句,转换数据类型
    最简单的办法就是把systimestamp转成普通的TIMESTAMP类型,让驱动能正常处理:

    select cast(systimestamp as timestamp) from dual
    

    这样返回的结果就是标准的TIMESTAMP类型,RowSet.populate()就能顺利识别并处理了。

  • 升级JDBC驱动版本
    ojdbc6是针对JDK 6/7设计的,在JDK 8下对一些Oracle特定的类型支持不够完善。你可以换成ojdbc7.jar或者ojdbc8.jar,高版本的驱动已经修复了这类类型映射的问题,能正确识别TIMESTAMP WITH TIME ZONE类型,直接用原来的查询语句也不会报错。

  • 手动遍历ResultSet填充RowSet
    如果暂时没法改查询语句或者升级驱动,那就绕过populate()方法,自己手动处理ResultSet的数据:

    // 假设你用的是CachedRowSet
    CachedRowSet rowset = new CachedRowSetImpl();
    rowset.setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
    rowset.setConcurrency(ResultSet.CONCUR_READ_ONLY);
    rowset.setTableName("dual");
    
    while (rs.next()) {
        rowset.moveToInsertRow();
        // 这里可以根据需求选择getTimestamp或者getString来获取值
        rowset.setTimestamp(1, rs.getTimestamp(1));
        rowset.insertRow();
        rowset.moveToCurrentRow();
    }
    

    这种方式完全由你控制类型转换,不会触发驱动和RowSet之间的类型识别问题。

内容的提问来源于stack exchange,提问作者Jefferson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:30:55