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

升级ojdbc8至ojdbc17后查询DATE字段触发ORA-18716错误

Oracle DATE字段查询在ojdbc17升级后抛出ORA-18716错误

问题背景

Java应用基于Oracle数据库开发,多张数据表包含DATE类型字段。使用ojdbc8 19.8.0.0驱动时,查询DATE字段并将结果存入Instant类型变量的逻辑可正常运行;但升级至ojdbc17 23.7.0.25.01驱动后,执行这类查询会抛出以下错误:

Could not extract column [1] from JDBC ResultSet [ORA-18716: {0} not in any time zone.DATE] [n/a]

示例代码

@PersistenceContext
private EntityManager em;

String sqlQueryString = "SELECT h.commentDate FROM CommentsHistory as h WHERE h.revisionId = 4878";

TypedQuery<Instant> resolvedCommentDateQuery = em.createQuery(sqlQueryString, Instant.class);

try {
    // 此处抛出错误!
    List<Instant> instantList = resolvedCommentDateQuery.getResultList();
    return null;
} catch (NoResultException nre) {
    return null;
}

依赖配置

原可正常运行的pom依赖:

<!-- Oracle JDBC Driver -->
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>19.8.0.0</version>
</dependency>

升级后触发错误的pom依赖:

<!-- Oracle JDBC Driver -->
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc17</artifactId>
    <version>23.7.0.25.01</version> 
</dependency>

解决方案

原因

Oracle DATE类型本身不包含时区信息,而Instant是带UTC时区的时间戳。ojdbc17新版本对日期类型映射做了更严格校验,不再允许无时区的DATE直接隐式转换为带时区的Instant,旧版ojdbc8则默认用数据库服务器时区补全转换。

解决方法

  1. 修改查询语句,显式做时区转换
    将DATE字段转换为带时区的时间戳,例如转换为UTC时区:

    SELECT CAST(h.commentDate AS TIMESTAMP WITH TIME ZONE) AT TIME ZONE 'UTC' FROM CommentsHistory as h WHERE h.revisionId = 4878
    

    或使用数据库会话时区转换:

    SELECT FROM_TZ(CAST(h.commentDate AS TIMESTAMP), SESSIONTIMEZONE) FROM CommentsHistory as h WHERE h.revisionId = 4878
    
  2. 调整返回类型,手动转换
    将查询返回类型改为LocalDateTime(匹配DATE的无时区特性),后续如需Instant再手动指定时区转换:

    TypedQuery<LocalDateTime> resolvedCommentDateQuery = em.createQuery(sqlQueryString, LocalDateTime.class);
    // 转换为Instant(示例用UTC时区)
    List<Instant> instantList = resolvedCommentDateQuery.getResultList()
        .stream()
        .map(ltd -> ltd.atZone(ZoneId.of("UTC")).toInstant())
        .collect(Collectors.toList());
    
  3. 临时恢复旧版驱动行为(不推荐)
    在JDBC URL中添加参数oracle.jdbc.mapDateToTimestampWithTimeZone=false,强制驱动沿用旧版的DATE映射逻辑,但可能引发其他兼容性问题,仅作为临时过渡方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 05:55:04