You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JDK8+Spring Boot1.5.3与JDK21+Spring Boot2.7.16存储过程日期返回类型差异

存储过程返回日期类型跨环境差异的原因分析与解决办法

执行存储过程后,ScheduledStartDate字段的返回值在不同环境存在明显差异:

  • JDK 8 + Spring Boot 1.5.3-RELEASE:返回时间戳格式(如1704479400000)
  • JDK 21 + Spring Boot 2.7.16:返回日期时间字符串格式(如2024-01-06 17:00:00.0)

相关代码

Java执行代码:

Map<String, Object> result = simpleJdbcCall.execute(sqlParameter);

存储过程代码:

BEGIN
    SELECT *
    FROM WorkOrder
    WHERE (RowNo BETWEEN @PageSize * (@PageNumber - 1) + 1 AND @PageNumber * @PageSize)
       OR (RowNo = 0 AND FromDate >= @FromDate AND FromDate < @Todate)
    ORDER BY DeliveryDate, status, WorkOrderID, FromDate
END

已尝试将MS SQL Server驱动从12.4降级至6.4,问题未解决。


原因分析

  • Spring JDBC版本逻辑差异:Spring Boot 2.x依赖的Spring 5.x对比1.x的Spring 4.x,对JDBC类型映射逻辑做了调整。Spring 5.x强化了对Java 8+日期API(如LocalDateTime)的原生支持,不再默认将数据库日期类型转为时间戳,而是根据驱动返回的类型直接映射,导致表现差异。
  • JDK与驱动的适配逻辑变化:SQL Server驱动的类型转换行为会随JDK版本变化。即使降级驱动到6.4,该版本在JDK 21环境下的类型解析逻辑和JDK 8环境下不一致——比如对java.sql.Timestamp和字符串的优先级处理不同,最终导致返回格式变化。
  • 连接属性默认值差异:Spring Boot 2.x默认的数据库连接属性和1.x存在差异,例如SQL Server驱动的sendTimeAsDatetime参数,该参数不仅影响发送到数据库的日期格式,也会影响数据库返回日期时的解析方式,默认值的变化可能引发返回类型不同。

解决办法

1. 显式指定字段类型映射

在SimpleJdbcCall中通过declareParameters明确指定ScheduledStartDate的JDBC类型,强制Spring JDBC将其映射为Timestamp,再转换为时间戳:

simpleJdbcCall.declareParameters(
    new SqlOutParameter("ScheduledStartDate", Types.TIMESTAMP)
);

2. 统一代码层的日期转换逻辑

在获取返回值后,针对不同类型做统一转换,确保输出一致:

Object scheduledStartObj = result.get("ScheduledStartDate");
long scheduledStartTimestamp;

if (scheduledStartObj instanceof String) {
    // 解析日期字符串为时间戳
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
    LocalDateTime dateTime = LocalDateTime.parse((String) scheduledStartObj, formatter);
    scheduledStartTimestamp = dateTime.atZone(ZoneId.systemDefault())
                                      .toInstant()
                                      .toEpochMilli();
} else if (scheduledStartObj instanceof Long) {
    scheduledStartTimestamp = (Long) scheduledStartObj;
} else if (scheduledStartObj instanceof Timestamp) {
    scheduledStartTimestamp = ((Timestamp) scheduledStartObj).getTime();
} else {
    // 处理其他异常情况
    scheduledStartTimestamp = 0;
}

3. 统一数据库连接属性

在配置文件中显式设置SQL Server驱动的相关参数,对齐新旧环境的行为:

# application.properties
spring.datasource.hikari.data-source-properties.sendTimeAsDatetime=true
spring.datasource.hikari.data-source-properties.useFmtOnly=false

4. 升级适配JDK 21的驱动版本

驱动6.4对JDK 21的支持并不完善,建议升级到官方支持JDK 21的最新SQL Server驱动版本(如12.6及以上),新版本通常会修复跨JDK版本的类型映射问题。

内容的提问来源于stack exchange,提问作者Sreejesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 21:06:12