如何编写单条数据库查询支持多日期条件、分页及可选参数筛选
单条查询实现多时间规则+可选用户筛选的分页查询
需求规则
需要通过单条查询语句覆盖所有查询逻辑,无需拆分多套SQL:
- 当
startDate、endDate均不为空:查询时间落在两者区间内的记录,支持分页 - 当
startDate为空、endDate不为空:查询时间早于endDate的记录,支持分页 - 当
startDate不为空、endDate为空:查询时间晚于startDate的记录,支持分页 - 额外支持
userIdentifier可选筛选:参数为空时不做用户维度过滤,传值时仅匹配对应用户的记录
原有初始代码
已编写的初始查询仅判断了userIdentifier为空的场景,缺失时间过滤、分页、用户传值匹配逻辑,代码如下:
@Query("SELECT m FROM notification m WHERE :userIdentifier is null") Flux<Notification> findAllByUserIdentifier(Timestamp startDate, Timestamp endDate, int page, int size);
实现代码
直接通过布尔逻辑组合所有分支条件即可,单条JPQL即可覆盖所有场景,分页建议直接使用Spring Data原生的Pageable参数,无需手动传递page、size计算偏移:
@Query("SELECT m FROM Notification m " + "WHERE (:userIdentifier IS NULL OR m.userIdentifier = :userIdentifier) " + "AND ( " + " (:startDate IS NOT NULL AND :endDate IS NOT NULL AND m.createTime BETWEEN :startDate AND :endDate) " + " OR (:startDate IS NULL AND :endDate IS NOT NULL AND m.createTime <= :endDate) " + " OR (:startDate IS NOT NULL AND :endDate IS NULL AND m.createTime >= :startDate) " + " OR (:startDate IS NULL AND :endDate IS NULL) " + ") ") Flux<Notification> findAllByCondition( @Param("userIdentifier") String userIdentifier, @Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate, Pageable pageable );
逻辑说明
所有条件通过OR分支匹配对应参数场景,不会出现逻辑冲突:
- 用户筛选逻辑:
userIdentifier传null时条件直接成立不做过滤,传值时仅匹配字段值等于入参的记录 - 时间筛选逻辑:完全对齐需求规则,额外覆盖了两个时间参数都为空的场景(此时不做时间范围过滤,查询全量符合用户条件的记录)
注意:如果你的实体类中存储时间的字段名不是
createTime,替换为实际字段名即可;响应式Spring Data场景下Pageable参数可被正常识别,自动完成分页逻辑。
内容的提问来源于stack exchange,提问作者Volatail
相关产品推荐
相关产品推荐

