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)

相关推荐
小蒜学长10 分钟前
springboot餐厅信息管理系统设计(代码+数据库+LW)
java·数据库·spring boot·后端
Justin_1913 分钟前
mysql数据库高级特性(一)
数据库·mysql
邂逅you1 小时前
用python操作mysql之pymysql库基本操作
数据库·python·mysql
心 一1 小时前
接口安全测试实战:从数据库错误泄露看如何构建安全防线
数据库·安全
点灯小铭1 小时前
基于单片机的PID调节脉动真空灭菌器上位机远程监控设计
数据库·单片机·嵌入式硬件·毕业设计·课程设计
小高Baby@1 小时前
Redis Key的设计
数据库·redis·缓存
q_19132846952 小时前
基于RuoYi框架+Mysql的汽车进销存后台管理系统
数据库·vue.js·spring boot·mysql·汽车·个人开发·若依
wuyunhang1234562 小时前
MySQL----锁
数据库·mysql
悟能不能悟3 小时前
springboot在DTO使用service,怎么写
java·数据库·spring boot
达瓦里氏1233 小时前
重排反应是什么?从分子变化到四大关键特征解析
数据库·学习·化学