QueryDsl:使用or()而不是()为条件生成错误的sql

时间:2015-12-19 10:19:18

标签: java postgresql querydsl

我在数据库中有表date_startdate_finish。它的日期范围和date_start <= date_finish。 我的代码中的日期范围也是Range(dateStart, dateFinish)dateStart <= dateFinish。 然后我想在DB表记录中找到哪个日期范围有交集(包括边框),并且在我的代码中有范围。

我为此条件编写了下一个生成BooleanExpression的函数:

public static BooleanExpression dateRangeIntersection(Range<Date> range, TemporalExpression<Date> pathStart, TemporalExpression<Date> pathFinish) {
        return pathStart.gt(range.getLast()).
                or(pathFinish.lt(range.getFirst())).
                not();
    }

我希望得到下一个sql条件(示例日期范围从2016-01-01到2016-01-04):

SELECT * FROM table t WHERE NOT (t.date_start > '2016-01-04' OR t.date_finish < '2016-01-01')

结果是:

SELECT * FROM table t WHERE t.date_start <= '2016-01-04' AND t.date_finish >= '2016-01-01'

这种情况是错误的,因为当表中的范围完全包含在范围[2016-01-01,2016-01-04]中时,它只能用于一种情况。

我认为QueryDsl试图理解条件并重写它更简单。但在这种情况下,它会让它错误。

有没有人知道如何在querydsl或重写条件中禁用条件优化以获得预期的sql?

1 个答案:

答案 0 :(得分:1)

NOT合并到子表达式时,会反转所有比较(例如=变为<>>变为<=)并交换{{1 } vs AND,所以这两个表达式是相同的:

OR

这正是你所拥有的。它做得很好。

您的情况变为:NOT (a > b OR c < d) a <= b AND c >= d

当你说只有完全包含在范围t.date_start <= '2016-01-04' AND t.date_finish >= '2016-01-01'中的表格中的范围可行时,你就错了。

尝试[2016-01-01, 2016-01-04]

[2015-10-25, 2016-01-02]

是的,按预期工作:t.date_start <= '2016-01-04' AND t.date_finish >= '2016-01-01' `2015-10-25` <= '2016-01-04' AND `2016-01-02` >= '2016-01-01' TRUE AND TRUE [2015-10-25, 2016-01-02]相交。