前言
在开发过程中,我们常常会遇到由于日期格式不匹配而导致的数据查询异常问题。今天,我就碰到了这样一个场景:在使用MyBatis Plus的Lambda表达式进行时间范围查询时,由于数据库中createTime
字段的格式与前端传来的查询参数格式不符,导致预期的数据无法正确查询出来。
问题描述
在使用MyBatis Plus的动态查询条件LambdaQueryWrapper
时,代码如下:
java
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
SysOss::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
其中,SysOss
表中的createTime
字段存储的是yyyy-MM-dd HH:mm:ss
格式的时间戳,而前端传过来的查询参数beginCreateTime
和endCreateTime
则是yyyy-MM-dd
格式的日期。这就导致了一个问题:当我们想查询某一天的全部记录时,比如数据库中有一条记录为2024-03-26 19:07:00
,而查询条件为beginCreateTime
和endCreateTime
都为2024-03-26
,原生的between条件查询因为时间精度不匹配而查不到这条记录。
解决方案
针对这个问题,我提出了两种不同的解决策略。
方案一:扩展查询条件至当日最末时刻
修改查询条件为:
java
// 注意23:59:59前的空格不能省略
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
SysOss::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime") + " 23:59:59");
在这个方案中,我们将结束时间参数endCreateTime
扩展为当天的23点59分59秒,这样一来,只要createTime
在指定日期的任何时刻都会被包含在查询范围内。
方案二:按日期截断进行比较
另外一种更为精准的解决方案是调整SQL语句,使其仅基于日期部分进行比较:
java
// 开始时间
lqw.apply(params.get("beginCreateTime") != null,
"date_format(`create_time`, '%Y-%m-%d') >= date_format({0}, '%Y-%m-%d')", params.get("beginCreateTime"));
// 结束时间
lqw.apply(params.get("endCreateTime") != null,
"date_format(`create_time`, '%Y-%m-%d') <= date_format({0}, '%Y-%m-%d')", params.get("endCreateTime"));
这种方式中,我们利用MySQL的date_format
函数将createTime
字段转换为日期格式并与查询参数进行比较,确保只关注日期部分而不考虑具体时间。
总结
通过对日期查询方式进行适当的调整,我们成功解决了由于日期格式不一致引发的查询bug。两种方案各有优势,第一种方案简洁直观,适用于无需严格区分同一天内不同时间记录的情况;第二种方案更为严谨,确保了按自然天进行精确筛选。在实际开发中,可以根据业务需求选择合适的解决方案。