时间类型格式化问题踩坑

记一次时间类型格式化问题:Hutools DbUtil 拼接 SQL 时如何避免日期精度丢失?

一、问题背景

在一次上游服务 SDK 开发中,我们需要通过 Hutools 工具包中的 DbUtil 实现数据持久化。在拼接 SQL 更新语句时,遇到了一个隐蔽的日期格式化问题。核心代码如下:

java 复制代码
Entity.create("table_name")
      .set("start_time", "<= " + xxx.getDate()) // 直接拼接日期对象
      .set("end_time", "IS NULL"));

其中 xxx.getDate() 对应实体类的字段定义如下:

java 复制代码
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "GMT+8")
private Date date; // 期望保留毫秒精度

问题现象

数据库记录中的 start_time 字段丢失了毫秒(SSS)精度,导致时间范围查询出现误差。


二、问题分析

1. 为什么会出现精度丢失?

  • 直接字符串拼接xxx.getDate() 返回 java.util.Date 对象,调用 toString() 方法时默认格式为 EEE MMM dd HH:mm:ss zzz yyyy不包含毫秒信息
  • 注解作用范围@JsonFormat 仅在 Jackson 序列化/反序列化 JSON 时生效,不影响 Date.toString() 的行为。

2. 错误示例分析

java 复制代码
// 假设 date 值为 2023-10-01 12:34:56.789
String sql = "<= " + date.toString();
// 实际拼接结果:<= Sat Oct 01 12:34:56 CST 2023

三、解决方案

1. 手动格式化日期(基础版)

通过 SimpleDateFormat 指定包含毫秒的格式:

java 复制代码
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String formattedDate = sdf.format(xxx.getDate());

Entity.create("table_name")
      .set("start_time", "<= '" + formattedDate + "'") // 注意添加引号

2. 使用 Hutools 工具类(推荐)

利用 DateUtil.format() 简化操作,避免重复造轮子:

java 复制代码
import cn.hutool.core.date.DateUtil;

String formattedDate = DateUtil.format(xxx.getDate(), "yyyy-MM-dd HH:mm:ss.SSS");

Entity.create("table_name")
      .set("start_time", "<= '" + formattedDate + "'")

四、避坑指南

1. SQL 注入风险

直接拼接字符串存在安全隐患,建议改用 预编译占位符

java 复制代码
// 使用 Hutools 的预编译方式
Entity entity = Entity.create("table_name")
                     .set("start_time", new Condition("<= ?", formattedDate));

2. 时区一致性

确保数据库连接时区与 @JsonFormatGMT+8 一致,避免时差问题。


五、总结

关键点 说明
Date.toString() 默认不包含毫秒,不可依赖其生成 SQL 字符串
@JsonFormat 局限 仅作用于 JSON 序列化,不影响其他场景的日期格式
手动格式化 使用 SimpleDateFormat 或 Hutools 工具类指定明确格式
安全拼接 优先使用预编译语句,避免拼接字符串带来的 SQL 注入风险

最佳实践

  • 始终通过 显式格式化 控制日期字符串的输出。
  • 涉及时间比较时,确保数据库字段类型与精度(如 DATETIME(3))和代码格式一致。
相关推荐
Chase_Mos3 小时前
Spring 必会之微服务篇(1)
java·spring·微服务
小林学习编程5 小时前
SpringBoot校园失物招领信息平台
java·spring boot·后端
撸码到无法自拔6 小时前
docker常见命令
java·spring cloud·docker·容器·eureka
heart000_16 小时前
IDEA 插件推荐:提升编程效率
java·ide·intellij-idea
ŧ榕树先生7 小时前
查看jdk是否安装并且配置成功?(Android studio安装前的准备)
java·jdk
未来的JAVA高级开发工程师7 小时前
适配器模式
java
LUCIAZZZ7 小时前
JVM之内存管理(一)
java·jvm·spring·操作系统·springboot
D_aniel_7 小时前
排序算法-计数排序
java·排序算法·计数排序
极小狐7 小时前
极狐GitLab 通用软件包存储库功能介绍
java·数据库·c#·gitlab·maven
旧故新长7 小时前
Browserless 快速上手
java