news 2026/7/19 5:29:18

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
为什么ORACLE使用JDBC查询SYSDATE时,RS.getDate能获取到时间部分?
  1. 这是个什问题?
    在某些版本ORACLE对应的JDBC驱动中,使用查询语句select sysdate from dual,使用rs.getDate获取到日期包含时间部分.而其他大部分数据库返回都不会包含时间部分.间接造成在做信创迁移时,造成时间部分丢失.

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

✅ [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的驱动去掉了时间部分
  1. 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;
}

  1. 知道原因,那如何使用呢?
    目前知道时间部分存在的原因,如果目前希望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).createFromDate(InternalDate) line: 67
SqlDateValueFactory.localCreateFromTimestamp(InternalTimestamp) line: 120
SqlDateValueFactory.localCreateFromTimestamp(InternalTimestamp) line: 50
SqlDateValueFactory(AbstractDateTimeValueFactory).createFromTimestamp(InternalTimestamp) line: 87
MysqlTextValueDecoder.decodeTimestamp(byte[], int, int, ValueFactory) line: 79
ByteArrayRow(AbstractResultsetRow).decodeAndCreateReturnValue(int, byte[], int, int, ValueFactory) line: 87
ByteArrayRow(AbstractResultsetRow).getValueFromBytes(int, byte[], int, int, ValueFactory) line: 241
ByteArrayRow.getValue(int, ValueFactory) line: 91
ResultSetImpl.getDate(int) line: 740
5. 信创总结
在适配ORACLE数据信创时,由于oracle返回了日期时间的部分.导致迁移到其他数据库时,返回前端的JSON日期串,时间部分丢失了.此时要做信创适配,有一下三种途径

修改业务代码,需要显示时间的代码,统一调整成rs.getTimestamp

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

AM62L CBASS硬件防火墙配置实战:从寄存器解析到多域安全策略

1. 项目概述在嵌入式系统,尤其是汽车电子和工业控制这类对功能安全和信息安全要求极高的领域,SoC内部的安全架构设计是决定产品成败的关键。我最近在基于德州仪器AM62L Sitara™处理器开发一个涉及多域隔离的项目时,深入研究了其CBASS模块中的…

作者头像 李华
网站建设 2026/7/19 5:27:50

污水提升泵售后哪家强?看准这三点不踩坑

家里装修地下室,还是开餐饮店需要解决排水问题,买一台污水提升泵似乎是绕不开的选择。但很多人在选购时,往往只盯着价格和参数,忽略了“售后”这个决定长期使用体验的关键环节。作为一个在行业内摸爬滚打多年的老兵,我…

作者头像 李华
网站建设 2026/7/19 5:27:41

Ofd2Pdf:5分钟掌握OFD转PDF的本地化高效解决方案

Ofd2Pdf:5分钟掌握OFD转PDF的本地化高效解决方案 【免费下载链接】Ofd2Pdf Convert OFD files to PDF files. 项目地址: https://gitcode.com/gh_mirrors/ofd/Ofd2Pdf 在数字化办公日益普及的今天,OFD转PDF已经成为许多用户必须面对的文档处理需求…

作者头像 李华
网站建设 2026/7/19 5:27:16

策略从研究端迁到券商端:字段映射、权限和订单回报逐项核对

策略从研究端迁到券商端,经常卡在字段含义和账户状态,而非买卖公式本身。牛股王股票这类低门槛量化辅助软件适合普通投资者先把条件、回测、调仓提醒与风控记录跑通;QMT和PTrade进入券商侧后,需要继续处理证券代码、目标仓位、可用…

作者头像 李华
网站建设 2026/7/19 5:27:06

SDRAM控制器子系统:防火墙、VRFB与调度器深度解析

1. 项目概述:深入SDRAM控制器子系统的核心在嵌入式系统和SoC的设计中,内存控制器扮演着连接处理器核心与外部动态存储器的桥梁角色,其性能、稳定性和安全性直接决定了整个系统的上限。我们常说的SDRAM控制器,远不止是一个简单的地…

作者头像 李华
网站建设 2026/7/19 5:26:16

Node.js核心价值与六大实战场景深度解析

1. Node.js的核心价值解析作为一名长期奋战在一线的全栈开发者,我亲历了Node.js从诞生到成为现代Web开发标配的全过程。Node.js本质上是一个基于Chrome V8引擎的JavaScript运行时环境,它让JavaScript突破了浏览器的桎梏,拥有了操作文件系统、…

作者头像 李华