ResultSet.getDate() 总是返回00:00:00,因为java.sql.Date语义仅表示日期,JDBC驱动将Oracle DATE字段映射为该类型时强制归零时分秒;应使用getTimestamp()配合Calendar避免时区偏移。
ResultSet.getDate() 为什么总是返回 00:00:00
因为 java.sql.date 的设计语义就是「仅日期」:它继承自 java.util.date,但构造时会强制把时分秒、毫秒全部归零,并在 tostring() 中只显示 yyyy-mm-dd。jdbc 驱动(如 ojdbc8)对 oracle date 字段的默认映射就是 java.sql.date,哪怕数据库里存的是 2026-05-09 14:20:33,rs.getdate("col") 拿到的也是 2026-05-09 00:00:00。
这不是 bug,是 JDBC 规范对「DATE」类型的语义约定——它不承诺保留时间部分。你查 rsmd.getColumnTypeName(i) 会看到类型名确实是 DATE,但驱动按规范做了裁剪。
getTimestamp() 能读出时分秒的根本原因
ResultSet.getTimestamp(String) 绕过了「日期语义」映射,直接把 Oracle DATE 字段底层的二进制时间值(含时分秒,精度到秒)解包成 java.sql.Timestamp。这个类本身支持完整时间戳,且 Oracle JDBC 驱动对 DATE 和 TIMESTAMP 字段都用同一套时间解析逻辑处理。
- 必须用
rs.getTimestamp("col"),不是rs.getObject("col")(后者仍可能返回java.sql.Date) - 如果字段实际是
DATE类型,getTimestamp()返回的Timestamp秒后小数位恒为.0(OracleDATE不存毫秒) - 若需
LocalDateTime,直接链式调用:rs.getTimestamp("col").toLocalDateTime(),无需中间转Date
时区错乱比丢时分秒更隐蔽
rs.getTimestamp("col") 看似能读出时间,但如果 JVM 时区和数据库服务器时区不一致,值可能偏移。例如 Oracle 存的是东八区时间 2026-05-09 14:20:33,而 JVM 时区设为 UTC,则 getTimestamp() 默认按 UTC 解析,结果变成 2026-05-09 06:20:33(相差 8 小时)。
唯一可靠方式是显式传入 Calendar:
立即学习“Java免费学习笔记(深入)”;
Calendar tz = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
Timestamp ts = rs.getTimestamp("col", tz);
注意:rs.getTimestamp(String, Calendar) 是必须项,不是可选项;rs.getTimestamp(String) 在跨时区场景下等同于埋雷。
别碰 getDate() + getTime() 拼接这种方案
有人试过 rs.getDate("col") + " " + rs.getTime("col"),这看似能凑出完整时间,但问题极多:
-
getDate()和getTime()分别走不同映射路径,可能从不同物理列或缓存中读,时间不一致 -
getTime()返回java.sql.Time,它没有日期上下文,无法保证对应同一天 - SQL 层面无保障,驱动行为随版本变化(ojdbc6 曾尝试改默认映射,ojdbc8 又回调)
真正稳定的做法只有一条路:用 getTimestamp(),配 Calendar,转 LocalDateTime 或 ZonedDateTime 按需处理。其他都是临时补丁,上线后容易在某个凌晨三点崩掉。


















