今天在使用mybatis-plus进行日期查询的时候遇到的一个问题,在这里记录一下。
需求: 前端传来signLogDate字段,如果signLogDate值为一个日期的话,后端就返回该指定日期的数据。如果值为null的话,后端就返回所有数据。
当时思路: 当时想这不就是经典的多条件筛选查询嘛,查询指定日期的数据,使用mysql的内置函数TO_DAYS() 。加个if判断,如果前端传来的字段不为null,就加上指定条件,否则就不加。当时想的sql如下:
select * from sign_log where TO_DAYS(in_time) = TO_DAYS('2022-1-8')
于是我就写了如下代码:
public Result queryTodaySignLog(@RequestBody SelectSignLogCondition selectCondition) {
Page<SignLog> page = new Page<SignLog>(selectCondition.getPageNum(), selectCondition.getPageSize());
QueryWrapper<SignLog> queryWrapper = new QueryWrapper<SignLog>();
if (selectCondition.getSignLogDate() != null) {
String date = "TO_DAYS('" + selectCondition.getSignLogDate() + "')";
queryWrapper.eq("TO_DAYS(in_time)", date);
}
return ResultUtil.success("查询成功", signLogService.list(queryWrapper));
}
启动运行,控制台sql打印出来如下:
JDBC Connection [HikariProxyConnection@1636116864 wrapping com.mysql.cj.jdbc.ConnectionImpl@21cde11d] will not be managed by Spring
==> Preparing: SELECT * FROM sign_log WHERE (TO_DAYS(in_time) = ?)
==> Parameters: TO_DAYS('2022-1-8')(String)
<== Total: 0
看着感觉没什么问题啊,但是就是查询不到结果。
我把它放在navicat下运行都能出结果,但是这里就是不出结果:
因为这点事我郁闷一下午,感觉很玄学,明明sql长的一模一样,为什么就是打印不出数据。
问题解决: 最后我发现是因为mybatis-plus中的QueryWrapper在拼接数据的时候,如果数据是(String)类型,他会自动在该数据的两侧加上引号,说明他是string类型。所以我上边的sql实际上被渲染成了这个样子:
select * from sign_log where TO_DAYS(in_time) = "TO_DAYS('2022-1-8')"
这当然什么都渲染不出来了,所以最后我还是用mybatis的方式,写了自定义sql来完成了这个功能。我就直接展示Mapper层的代码:
@Select("select * from sign_log where TO_DAYS(`in_time`) = TO_DAYS(#{signLogDate}) order by in_time desc")
IPage<SignLog> queryTodaySignLog(Page<SignLog> page,@Param("signLogDate") String signLogDate);
@Select("select * from sign_log order by in_time desc")
IPage<SignLog> queryAllSignLog(Page<SignLog> page);
由于没有办法进行拼接,所以我就只能写两个sql分开来查找完成这个功能。如果有大佬有更优雅的方式完成这个功能的话,欢迎评论区与我讨论,不胜感谢。