时间类型格式化问题踩坑

记一次时间类型格式化问题: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))和代码格式一致。
相关推荐
我该如何取个名字3 分钟前
Mac配置Java的环境变量
java·开发语言·macos
kkkkatoq8 分钟前
Java中的锁
java·开发语言
界面开发小八哥21 分钟前
「Java EE开发指南」用MyEclipse开发EJB 3无状态会话Bean(二)
java·ide·java-ee·eclipse·myeclipse
LCY13327 分钟前
spring security +kotlin 实现oauth2.0 认证
java·spring·kotlin
soulermax29 分钟前
数字ic后端设计从入门到精通2(含fusion compiler, tcl教学)
java·linux·服务器
我的代码永没有bug35 分钟前
day1-小白学习JAVA---JDK安装和环境变量配置(mac版)
java·学习·macos
王有品1 小时前
Spring MVC 一个简单的多文件上传
java·spring·mvc
Johnny Lnex1 小时前
JVM之经典垃圾回收器
java
那就摆吧1 小时前
数据结构-栈
android·java·c语言·数据结构
du fei1 小时前
C# 单例模式
java·单例模式·c#