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

如何获取PostgreSQL适配的日期极值解决JPA Criteria查询报错

解决JPA Criteria查询中PostgreSQL日期范围溢出问题

问题场景

我用JPA Criteria编写了文件过滤查询代码:

public class FileSpecification {

    public static Specification<FileEntity> getFilterdFiles(FilesFilterParams params) {
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            predicates.add(criteriaBuilder.between(root.get("uploadDate"),
                    params.getUploadDateFrom() == null ? new Date(Long.MIN_VALUE) : params.getUploadDateFrom(),
                    params.getUploadDateTo() == null ? new Date(Long.MAX_VALUE) : params.getUploadDateTo()));

            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }
}

需求是当params.getUploadDateFrom()或params.getUploadDateTo()为null时,用最小/最大日期替代,但执行时触发PostgreSQL报错:

org.postgresql.util.PSQLException: ERROR: timestamp out of range: "292269055-12-02 21:47:04.192+05 BC"

原因是java.util.Date(Long.MIN_VALUE)和java.util.Date(Long.MAX_VALUE)超出了PostgreSQL的timestamp类型范围。我知道可以拆分谓词用criteriaBuilder.lessThanOrEqualTo/criteriaBuilder.greaterThanOrEqualTo解决,但想了解如何获取PostgreSQL兼容的正确日期极值。

解决方案

1. 使用PostgreSQL兼容的日期极值

PostgreSQL的timestamp类型支持的范围是公元前4713年1月1日到公元294276年12月31日,可以用以下方式构造对应Java日期:

方式一:兼容Java 8之前版本(用Calendar)

// 构造PostgreSQL支持的最小日期
Calendar minCal = Calendar.getInstance();
minCal.set(4713, Calendar.JANUARY, 1, 0, 0, 0);
minCal.set(Calendar.MILLISECOND, 0);
Date pgMinDate = minCal.getTime();

// 构造PostgreSQL支持的最大日期
Calendar maxCal = Calendar.getInstance();
maxCal.set(294276, Calendar.DECEMBER, 31, 23, 59, 59);
maxCal.set(Calendar.MILLISECOND, 999);
Date pgMaxDate = maxCal.getTime();

修改原代码的替换逻辑:

predicates.add(criteriaBuilder.between(root.get("uploadDate"),
        params.getUploadDateFrom() == null ? pgMinDate : params.getUploadDateFrom(),
        params.getUploadDateTo() == null ? pgMaxDate : params.getUploadDateTo()));

方式二:Java 8+版本(用Instant)

// 最小日期
Date pgMinDate = Date.from(Instant.parse("-4713-01-01T00:00:00Z"));
// 最大日期
Date pgMaxDate = Date.from(Instant.parse("+294276-12-31T23:59:59.999Z"));

2. 更优雅的无边界条件写法(推荐)

不需要硬塞极值,直接根据参数是否为null动态添加谓词,数据库会自动匹配所有符合剩余条件的数据,既避免范围溢出,也减少不必要的范围判断:

public static Specification<FileEntity> getFilterdFiles(FilesFilterParams params) {
    return (root, query, criteriaBuilder) -> {
        List<Predicate> predicates = new ArrayList<>();
        
        if (params.getUploadDateFrom() != null) {
            predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("uploadDate"), params.getUploadDateFrom()));
        }
        if (params.getUploadDateTo() != null) {
            predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("uploadDate"), params.getUploadDateTo()));
        }

        return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
    };
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 17:57:17