在 JOOQ 中选择性地将 LIMIT 应用于查询的最佳方法是什么?我想跑步:
SelectSeekStepN<Record> readyToFetch = dslContext.select(selectFields).
from(derivedTable).
where(conditions).
orderBy(orderForward);
if (length != Integer.MAX_VALUE)
readyToFetch = readyToFetch.limit(length);
limit()
返回 SelectLimitPercentStep<Record>
,它不是 SelectSeekStepN<Record>
的子类,因此我收到编译器错误。
另一方面,如果我将
readyToFetch
的返回类型从 SelectSeekStepN<Record>
更改为与 Select<Record>
的返回类型兼容的 limit()
,那么我无法在 limit()
上调用 Select<Record>
。我需要明确地将其转换为 SelectSeekStepN<Record>
。
有更好的方法吗?
也许JOOQ应该将
Integer.MAX_VALUE
视为特殊值(无限制),以使这种代码更容易编写...
LIMIT
可以使用
Field
创建虚拟 DSL.noField(DataType)
表达式,例如,如此处记录的
dslContext.select(selectFields).
from(derivedTable).
where(conditions).
orderBy(orderForward).
limit(length != Integer.MAX_VALUE ? length : noField(INTEGER)).
fetch();
您自己的问题已经包含解决方案。这只是一个小打字问题。您可能选择将中间步骤分配给
SelectSeekStepN
,因为您的 IDE 建议使用这种类型。但您可以使用任何超级类型。
Select<Record> readyToFetch;
SelectLimitStep<Record> readyToLimit;
readyToFetch = readyToLimit = dslContext.select(selectFields).
from(derivedTable).
where(conditions).
orderBy(orderForward);
if (length != Integer.MAX_VALUE)
readyToFetch = readyToLimit.limit(length);
readyToFetch.fetch();
ParserImpl
逻辑中获得一些灵感。它到处都这样做。赋值表达式是一件幸事!
在条件表达式上使用类型推断的替代方法:
SelectLimitStep<Record> limit = dslContext.select(selectFields).
from(derivedTable).
where(conditions).
orderBy(orderForward);
Result<?> result = (length != Integer.MAX_VALUE ? limit.limit(length) : limit).fetch();
null
作为明确指示不存在 LIMIT
使用
null
来表示缺少 LIMIT
是一个非常糟糕的主意,至少有 3 个原因:
(Field<?>) null
解释为 NULL
绑定值或 NULL
文字,从不解释为不存在的值。如果我们突然只在 null
中使用
LIMIT
null
(缺失值的内部解释)和 null
(您作为用户通过 显式向 jOOQ 提供的值)。因此,无论如何,我们在内部都需要一些 noLimit()
对象来进行区分,在这种情况下,为什么不将其公开为 API,而不是让你随意修改呢?NULL
限制。 PostgreSQL 将其解释为不存在的 LIMIT
(我觉得这很令人困惑,LIMIT
是“未知”)。 Oracle 将其解释为 LIMIT 0
,这要合理得多。其他方言(例如 MySQL)将 LIMIT NULL
视为错误语法而拒绝,这也是合理的。您建议 jOOQ 覆盖此行为并巧妙地重新解释它。我宁愿不!我深入研究了实现,发现还有另一种方法
limit(Number)
将 null
值视为没有限制。因此,代码可以写成:
Select<Record> readyToFetch = dslContext.select(selectFields).
from(derivedTable).
where(conditions).
orderBy(orderForward).
limit(length == Integer.MAX_VALUE ? null : length);