news 2026/6/26 9:06:14

信创-为什么ORACLE使用JDBC查询SYSDATE时,RS.getDate能获取到时间部分?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
信创-为什么ORACLE使用JDBC查询SYSDATE时,RS.getDate能获取到时间部分?

这是个什问题?

在某些版本ORACLE对应的JDBC驱动中,使用查询语句select sysdate from dual,使用rs.getDate获取到日期包含时间部分.而其他大部分数据库返回都不会包含时间部分.间接造成在做信创迁移时,造成时间部分丢失.

由于测试代码简单,这里不提供代码部分,直接测试Oraclemysql两种数据的情况,同时经过测试返现,对应的kingbaseguassdb同样有一下情况

✅ [oracle] 数据库连接已建立 当前查询SQL:select sysdate from dual Date类型值=>93 getDate_FMT => 2026-05-03 21:30:34 getDate=> 2026-05-03 getTimestamp=>2026-05-03 21:30:34.0 ✅ [oracle] 数据库连接已关闭 ✅ [mysql] 数据库连接已建立 当前查询SQL:select sysdate() Date类型值=>93 getDate_FMT => 2026-05-03 00:00:00 getDate=> 2026-05-03 getTimestamp=>2026-05-03 21:30:34.0 ✅ [mysql] 数据库连接已关闭

针对以上输出结果可以反应了以下信息:

  • ORACLE 和 MYSQL日期列对应的TYPE值都是 93
  • 使用格式yyyy-MM-dd HH:mm:ss格式化,可以发现ORACL包含时间部分21:30:34
  • 当前的查询sql,复制到数据执行,不管是oracle还是mysql查询接口都包含了时间部分

以下是直接在mysql数据库执行的情况

sysdate() | -------------------| 2026-05-03 21:36:24|

通过这些输出信息可以得到一个结论:数据库底层查询sysdate都是包含时间部分的,只是有些JDBC的驱动去掉了时间部分

2. Oracle的JDBC驱动是如何处理的呢?

带着上边的疑问,我分析了ojdbc8-19.7.0.0.jar的源码,找到对应的处理逻辑.由此发现,Oracle针对这种情况,还提供了专门的配置oracle.jdbc.DateZeroTime,让用户确定是否保留日期类型的时间部分

那这部分代码到底在哪里呢?以下是我定位到堆栈信息

T4CDateAccessor(DateTimeCommonAccessor).getDate(int) line: 135 T4CStatement(GeneratedStatement).getDate(long, int) line: 163 ForwardOnlyResultSet(GeneratedScrollableResultSet).getDate(int) line: 186 Multdbtest.testSysdate() line: 138

由此我们可以知道,Oralce处理日期的类是DateTimeCommonAccessor

我们看下这部分代码

Date getDate(int paramInt, Calendar paramCalendar) throws SQLException { Calendar calendar; if (isNull(paramInt)) return null; if (paramCalendar == null) { calendar = this.statement.getDefaultCalendar(); } else { calendar = (Calendar)paramCalendar.clone(); } getBytesInternal(paramInt, this.tmpBytes); int i = oracleYear(this.tmpBytes); calendar.clear(); calendar.set(1, i); calendar.set(2, oracleMonth(this.tmpBytes)); calendar.set(5, oracleDay(this.tmpBytes)); if (OracleDriver.getSystemPropertyDateZeroTime()) { calendar.set(11, 0); calendar.set(12, 0); calendar.set(13, 0); } else { calendar.set(11, oracleHour(this.tmpBytes)); calendar.set(12, oracleMin(this.tmpBytes)); calendar.set(13, oracleSec(this.tmpBytes)); } calendar.set(14, 0); if (i > 0 && calendar.isSet(0)) { calendar.set(0, 1); } return new Date(calendar.getTimeInMillis()); }

其中有一部分关键代码if (OracleDriver.getSystemPropertyDateZeroTime())如果这个值为true,就直接把时间部分值设置成0了,否则,就取数据返回的时间部分的信息.

OracleDriver.getSystemPropertyDateZeroTime这个函数,从函数名基本可以知道它的意图,应该是获取SystemProperty,这些信息可以通过启动时注入.那我们推测是否是正确的呢?

public static boolean getSystemPropertyDateZeroTime() { String str = PhysicalConnection.getSystemPropertyDateZeroTime("false"); return str.equalsIgnoreCase("true"); }

从这里代码只知道,可以大概推测到,这方法默认值返回的是false,就是要获取数据库返回的时间部分,我们继续往下追代码

static String getSystemPropertyDateZeroTime(String defaultValue) { return getSystemProperty("oracle.jdbc.DateZeroTime", defaultValue); } private static String getSystemProperty(String configKey, String defaultValue) { if (configKey != null) { final String fstr = configKey; final String fdefaultValue = defaultValue; final String[] rets = { defaultValue }; AccessController.doPrivileged(new PrivilegedAction() { public Object run() { rets[0] = System.getProperty(fstr, fdefaultValue); return null; } }); return rets[0]; } return defaultValue; }

3. 知道原因,那如何使用呢?

目前知道时间部分存在的原因,如果目前希望rs.getDate返回的日期,跟其他数据库保一样不返回时间部分,就可以设置oracle.jdbc.DateZeroTime=true,对应测试代码如下:

String exesql = "select sysdate "; if (dbName == "oracle") { exesql += " from dual"; System.setProperty("oracle.jdbc.DateZeroTime", "true"); }

4. MYSQL是如何处理的呢?

通过跟踪代码,数据也是返回了日期类型的,但是rs.getDate使用的是SqlDateValueFactory做了值转换,可以找到这个类,跟踪一下方法.

public Date localCreateFromDate(InternalDate idate) { synchronized (this.cal) { try { if (idate.isZero()) { throw new DataReadException(Messages.getString("ResultSet.InvalidZeroDate")); } this.cal.clear(); this.cal.set(idate.getYear(), idate.getMonth() - 1, idate.getDay()); long ms = this.cal.getTimeInMillis(); return new Date(ms); } catch (IllegalArgumentException e) { throw ExceptionFactory.createException(WrongArgumentException.class, e.getMessage(), e); } } }

从以上代码可以知道,mysql只赋值了了年月日,对应调试的堆栈信息如下

SqlDateValueFactory.localCreateFromDate(InternalDate) line: 80 SqlDateValueFactory.localCreateFromDate(InternalDate) line: 50 SqlDateValueFactory(AbstractDateTimeValueFactory<T>).createFromDate(InternalDate) line: 67 SqlDateValueFactory.localCreateFromTimestamp(InternalTimestamp) line: 120 SqlDateValueFactory.localCreateFromTimestamp(InternalTimestamp) line: 50 SqlDateValueFactory(AbstractDateTimeValueFactory<T>).createFromTimestamp(InternalTimestamp) line: 87 MysqlTextValueDecoder.decodeTimestamp(byte[], int, int, ValueFactory<T>) line: 79 ByteArrayRow(AbstractResultsetRow).decodeAndCreateReturnValue(int, byte[], int, int, ValueFactory<T>) line: 87 ByteArrayRow(AbstractResultsetRow).getValueFromBytes(int, byte[], int, int, ValueFactory<T>) line: 241 ByteArrayRow.getValue(int, ValueFactory<T>) line: 91 ResultSetImpl.getDate(int) line: 740

5. 信创总结

在适配ORACLE数据信创时,由于oracle返回了日期时间的部分.导致迁移到其他数据库时

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 9:01:29

Pearcleaner:解决macOS应用残留清理问题的开源工具指南

Pearcleaner&#xff1a;解决macOS应用残留清理问题的开源工具指南 【免费下载链接】Pearcleaner A free, source-available and fair-code licensed mac app cleaner 项目地址: https://gitcode.com/gh_mirrors/pe/Pearcleaner macOS应用卸载后遗留的缓存、偏好设置和支…

作者头像 李华
网站建设 2026/6/26 9:00:03

百度网盘解析工具完整教程:免费获取高速下载链接的终极指南

百度网盘解析工具完整教程&#xff1a;免费获取高速下载链接的终极指南 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 还在为百度网盘的速度限制而烦恼吗&#xff1f;想要摆脱…

作者头像 李华
网站建设 2026/6/26 8:56:43

RLHF 与大模型对齐:从 PPO 到 DPO

摘要&#xff1a;ChatGPT 的成功不仅来自 GPT 模型本身&#xff0c;更来自一个关键的训练步骤——RLHF&#xff08;Reinforcement Learning from Human Feedback&#xff0c;基于人类反馈的强化学习&#xff09;。RLHF 用强化学习的方法&#xff0c;让大模型的输出与人类的偏好…

作者头像 李华
网站建设 2026/6/26 8:56:21

计算机毕业设计之基于SSM的房屋出租管理系统设计与实现

当下社会&#xff0c;信息技术充斥社会各个领域&#xff0c;已融入人们生活的点滴&#xff0c;日常中人们管理信息、办理业务、购买商品等都可以网络线上进行&#xff0c;快速而又便利&#xff0c;特别是随着移动互联网时代的到来&#xff0c;更是让人们随时享受着网络给带来的…

作者头像 李华
网站建设 2026/6/26 8:56:13

一次智能展厅改造经历,让我看清了交互体验的价值

当展厅不再只是“看”&#xff0c;而是让人“走进去”你是否也见过这样的场景&#xff1f;精心设计的展厅里&#xff0c;观众匆匆走过&#xff0c;目光扫过展板便转身离开。传统陈列像一本合上的书&#xff0c;而今天的人们渴望亲手翻开它。上海点山展览展示有限公司的科技智能…

作者头像 李华