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

如何通过CriteriaQuery从timestamp列中查询指定日期的数据?

问题根源

数据库的timestamp字段包含完整的年月日时分秒信息,你通过SimpleDateFormat解析2023-07-27得到的Date对象是当天的00:00:00,只有当数据库中createdAt的时间恰好等于这个时刻时,equal才会匹配,自然查不到当天其他时间点的数据。

解决方案

这里提供两种可靠的实现方式:

方案1:查询当天完整时间范围

构造当天的起始时间(00:00:00)和结束时间(23:59:59.999),通过between做范围匹配:

List<Predicate> predicates = new ArrayList<>();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date startDateObj = dateFormat.parse(startDate);

// 计算当天结束时间:起始日期加1天,再减1毫秒
Calendar calendar = Calendar.getInstance();
calendar.setTime(startDateObj);
calendar.add(Calendar.DAY_OF_MONTH, 1);
calendar.add(Calendar.MILLISECOND, -1);
Date endDateObj = calendar.getTime();

if (request.getKey().equals("createdAt")) {
    predicates.add(criteriaBuilder.between(root.get("createdAt"), startDateObj, endDateObj));
}

方案2:提取日期部分直接比较

利用JPA的函数调用,提取createdAt的日期部分和目标日期对比(不同数据库函数略有差异):

List<Predicate> predicates = new ArrayList<>();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date targetDate = dateFormat.parse(startDate);

if (request.getKey().equals("createdAt")) {
    // MySQL 环境:用DATE()函数提取日期部分
    Expression<String> createdAtDate = criteriaBuilder.function(
        "DATE", 
        String.class, 
        root.get("createdAt")
    );
    String targetDateStr = dateFormat.format(targetDate);
    predicates.add(criteriaBuilder.equal(createdAtDate, targetDateStr));
    
    // PostgreSQL 环境:改用DATE_TRUNC()函数
    // Expression<Date> createdAtDate = criteriaBuilder.function(
    //     "DATE_TRUNC",
    //     Date.class,
    //     criteriaBuilder.literal("day"),
    //     root.get("createdAt")
    // );
    // predicates.add(criteriaBuilder.equal(createdAtDate, targetDate));
}
额外建议
  • 优先使用Java 8+的DateTimeFormatter替代SimpleDateFormat,后者线程不安全:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate targetLocalDate = LocalDate.parse(startDate, formatter);
// 转换为java.util.Date(如果需要适配旧代码)
Date targetDate = Date.from(targetLocalDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
  • 确认应用服务器和数据库的时区一致,避免时间转换导致的匹配偏差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:05:06