QueryDsl:使用 or() 和 not() 为条件生成错误的 sql
QueryDsl: generate wrong sql for condition with or() and not()
我在数据库中有 table 列 date_start
和 date_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]
相交。
我在数据库中有 table 列 date_start
和 date_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]
相交。