【发布时间】:2016-07-17 18:22:23
【问题描述】:
我有一个包含两个日期的范围日期选择器:start 和 end,两者都可以为空。我想过滤一个表,其中实体有一个确切的日期:date。
所以,这里有一些例子。我想配。成像要匹配的日期是当前日期 (17/07/2016)。
- null - 17/07/2016 -> 匹配
- 17/07/2016 - null -> 匹配
- 17/07/2016 - 17/07/2016 -> 匹配
- null - null -> 匹配所有
在我看来,这些是边缘情况,也是我如此挣扎的原因。
其实我的代码是这样的:
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Transaction> cq = cb.createQuery(Transaction.class);
Root<Transaction> root = cq.from(Transaction.class);
List<Predicate> predicates = new ArrayList<>();
Predicate startPredicate = cb.greaterThanOrEqualTo(root.get(Transaction_.date), start);
Predicate endPredicate = cb.greaterThanOrEqualTo(root.get(Transaction_.date), end);
predicates.add(startPredicate);
predicates.add(endPredicate);
cq.select(root).where(predicates.toArray(new Predicate[] {}));
TypedQuery<Transaction> query = getEm().createQuery(cq);
query.setFirstResult(firstRow);
query.setMaxResults(maxRow);
List<Transaction> resultList = query.getResultList();
我想得到这样的查询:
SELECT * FROM transaction
WHERE ((cast(date AS DATE) >= '2016-07-16' OR cast(date AS DATE) IS NULL))
AND ((cast(date AS DATE) <= '2016-07-17' OR cast(date AS DATE) IS NULL))
请注意:静态日期是模拟开始和结束日期。 date 是表格列。
我知道我的代码是错误的。它只匹配范围,不考虑空值。此外,如果开始和结束是同一天,我将得到零结果。
你有什么想法吗?如何编辑我的代码以匹配所有提到的模式?
【问题讨论】:
-
请先尝试在后端数据库上构造相应的SQL查询,直接产生预期结果。例如,您是否要显示开始日期(包括/不包括)和结束日期(包括/不包括)之间的所有行,包括
SELECT * FROM table_name WHERE (cast(start_date AS DATE) > '07/17/2016' OR cast(start_date AS DATE) IS NULL) AND (cast(end_date AS DATE) < '07/20/2016' OR cast(end_date AS DATE) IS NULL)等列中的空值(或使用BETWEEN子句)?这样就可以更容易、更清晰地制作相应的条件查询。 -
对不起,伙计,我没有考虑过这个选项。在我的脑海中只有标准 api,因为我认为查询很复杂(在我的脑海中)。到目前为止,您的查询看起来相当不错。我为我的问题添加了更新。你介意看看吗? :)
标签: date jpa criteria-api