QueryDsl:使用 or() 和 not() 为条件生成错误的 sql

QueryDsl: generate wrong sql for condition with or() and not()

我在数据库中有 table 列 date_startdate_finish。它是日期范围和 date_start <= date_finish。 我的代码中也有日期范围 class Range(dateStart, dateFinish)dateStart <= dateFinish。 然后我想在数据库 table 中找到日期范围与我的代码范围有交集(包括边界)的记录。

我为此条件编写了下一个生成 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'

这个条件是错误的,因为它只能服务于一种情况,即 table 中的范围完全包含在范围 [2016-01-01, 2016-01-04] 中。

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

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

当将 NOT 合并到子表达式中时,您反转所有比较(例如 = 变为 <> 并且 > 变为 <=)并交换 AND vs 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'

当您说只有 table 中的范围完全包含在 [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][2016-01-01, 2016-01-04] 相交。