oracle date字段在java中秒数变.0,是因getdate()强制归零时分秒;应改用gettimestamp()读取、settimestamp()写入,并配localdatetime或timestamp类型。
java读oracle date字段秒数变.0,不是数据丢了,是getdate()主动丢的
Oracle的DATE类型本身存的就是年月日+时分秒(精度到秒),数据库里明明是2026-05-14 15:23:47,Java里用ResultSet.getDate("created_at")取出来却变成2026-05-14 00:00:00——这不是bug,是java.sql.Date的设计行为:它只承诺表示“日期”,构造时会把时分秒强制归零。
为什么getDate()一定丢时间部分
java.sql.Date本质是java.util.Date的子类,但重写了toString()和构造逻辑,只保留year-month-day,其余全设为0。JDBC驱动看到Oracle DATE列,就按规范映射成这个类型,不加判断。
-
ResultSet.getObject("col")也一样,底层默认走getDate()路径,返回的仍是java.sql.Date -
PreparedStatement.setDate()写入时同样会清空时间,导致入库后只剩日期 - 即使你用
SimpleDateFormat格式化java.sql.Date对象,输出的时分秒永远是00:00:00,因为值本身就没有
用getTimestamp()能直接拿到完整时间
ResultSet.getTimestamp("col")不看字段声明类型,只管从网络包里原样提取时间戳字节,Oracle DATE里的时分秒它全认。返回的是java.sql.Timestamp,含秒、毫秒(虽然Oracle DATE没毫秒,但JDBC会补0)。
- 无需改数据库字段类型,
DATE列直接调getTimestamp()即可 - 搭配
LocalDateTime更干净:rs.getTimestamp("col").toLocalDateTime() - 如果用MyBatis,必须在
<resultmap></resultmap>里显式写jdbcType="TIMESTAMP",否则它可能按列名推断为DATE又掉坑里
写入时setTimestamp()也要配对使用
光读对了不行,写入也得一致。用PreparedStatement.setDate(1, date)往DATE列写LocalDateTime.now()转出的java.sql.Date,时间照样被清零。
- 改用
ps.setTimestamp(1, Timestamp.valueOf(localDateTime)) - 或者更稳妥:
ps.setObject(1, localDateTime, JDBCType.TIMESTAMP),强制走TIMESTAMP协议路径 - 旧版驱动(如ojdbc6)可能需连接URL加
?oracle.jdbc.javaTimeSupport=true
真正容易被忽略的是:这个问题和Oracle版本、NLS设置、时区都无关,纯属JDBC类型映射策略。只要代码里还混着getDate()或setDate(),哪怕驱动升级到ojdbc8,该丢还是丢。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











