Oralce TIMESTAMP 类型转换为 JSON 失败 | oracle.sql.TIMESTAMP 问题

问题场景

使用 springboot 做的某业务查询,使用的数据库是 Oracle 数据库,数据库中的字段 TRANS_TIME 使用的数据库字段类型是 TIMESTAMP。程序中在 MyBatis 的 XML 中编写了常规的 select 查询,<select id="queryData" resultType="java.util.Map">,这里因为实际业务需求原因没有将查询结果自动转换为 Java 对象,而是直接放到 Map 中返回给前端。

本意是希望前端能获取到查询的数据集合渲染,实际上发现这个 TIMESTAMP 类型的字段没有正常在 json 中显示时间。通过分析发现 map 中的 TRANS_TIME 字段对应的类型是 oracle.sql.TIMESTAMP,而不是 java.sql.Timestamp 类型(如果数据库字段是 DATE 类型则没有问题)。进一步得出结论 oracle.sql.TIMESTAMP 序列化和反序列化有问题,所以不能正常被 spring 的 MessageConvert 转换为 json。

鉴于上述问题和结论,查阅了 oracle 官方文档,获得如下原文说明

bash 复制代码
Footnote 1 ResultSet.getObject returns java.sql.Timestamp only if the oracle.jdbc.J2EE13Compliant connection property is set to TRUE, else the method returns oracle.sql.TIMESTAMP.

Note:

The ResultSet.getObject method returns java.sql.Timestamp for the TIMESTAMP SQL type, only when the connection property oracle.jdbc.J2EE13Compliant is set to TRUE. This property has to be set when the connection is obtained. If this connection property is not set or if it is set after the connection is obtained, then the ResultSet.getObject method returns oracle.sql.TIMESTAMP for the TIMESTAMP SQL type.
The oracle.jdbc.J2EE13Compliant connection property can also be set without changing the code in the following ways:

Including the ojdbc5dms.jar or ojdbc6dms.jar files in the CLASSPATH. These files set oracle.jdbc.J2EE13Compliant to TRUE by default. These are specific to the Oracle Application Server release and are not available as part of the general JDBC release. They are located in $ORACLE_HOME/jdbc/lib.

Setting the system property by calling the java command with the flag -Doracle.jdbc.J2EE13Compliant=true. For example,

java -Doracle.jdbc.J2EE13Compliant=true ...
When the J2EE13Compliant is set to TRUE the action is as in Table B-3 of the JDBC specification.

文中描述大概说的意思就是,oracle 驱动类默认使用 oracle.sql.TIMESTAMP 类型,如果希望使用 J2EE1.3及以后的标准,需要通过设置 JVM 参数 -Doracle.jdbc.J2EE13Compliant=true 来明确让它使用 java.sql.Timestamp 类型。

具体两种方式的示例就是:

1、启动 java 服务的时候通过 -Doracle.jdbc.J2EE13Compliant=true 设定。

2、在 java 程序的入口处硬编码使用 System.setProperty("oracle.jdbc.J2EE13Compliant", "true") 来设定。

这两种方式,做了测试验证,都有效,可以按需选择其一使用。

有兴趣的话,可以进一步查看 oracle 驱动源码,在 oracle.jdbc.driver.GeneratedPhysicalConnection 类的 readConnectionProperties 方法、oracle.jdbc.driver.TimestampAccessorgetObject 方法、oracle.jdbc.driver.DateTimeCommonAccessorgetTimestampgetTIMESTAMP 方法中,能看到关于该配置属性和对应时间类型的处理逻辑。

总结

通过设置属性 oracle.jdbc.J2EE13Compliant=true,可以使 oracle 的 timestamp 类型字段以 java.sql.Timestamp 类型返回,不设置时默认 false,返回 oracle.sql.TIMESTAMP,可能会导致序列化时类型转换失败等问题。


(END)

相关推荐
Cloud云卷云舒11 小时前
云卷云舒:从Oracle/MySQL迁移到HaishanDB:迁移评估工具核心技术拆解
mysql·oracle·ai-native·haishandb·信创数据库替换
憧憬成为web高手11 小时前
皮卡丘靶场速通--sql 2
数据库·sql·mybatis
段一凡-华北理工大学11 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
oradh13 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
z1234567898614 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
程序猿DD14 小时前
一个 API Key,统一调用大模型、生图和联网搜索
数据库·网关
TlSfoward15 小时前
抓包代理链路下的 TLS 指纹变化分析 TLSFOWARD抓包工具
数据库·爬虫·网络协议·搜索引擎·php
数智化管理手记16 小时前
账龄分析手工统计易遗漏?自动账龄分析工具怎么搭建
大数据·网络·数据库·人工智能·数据挖掘
LabVIEW开发16 小时前
NI Package Manager安装LabVIEW时InternalServerError错误
网络·数据库·labview·labview知识·labview功能·labview程序
SelectDB16 小时前
PostgreSQL 实时同步到 Apache Doris:一站式 CDC 解决方案
数据库