升级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则默认用数据库服务器时区补全转换。
解决方法
修改查询语句,显式做时区转换
将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调整返回类型,手动转换
将查询返回类型改为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());临时恢复旧版驱动行为(不推荐)
在JDBC URL中添加参数oracle.jdbc.mapDateToTimestampWithTimeZone=false,强制驱动沿用旧版的DATE映射逻辑,但可能引发其他兼容性问题,仅作为临时过渡方案。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

