如何在 JOOQ 中编写 OPTIONAL where 子句

How to write OPTIONAL where clauses in JOOQ

List<MyTable> result = DSL.using(configuration())
                .select()
                .from(MY_TABLE)
                .where(MY_TABLE.ID1.equal(pk_id1))
                        .and(MY_TABLE.ID2.equal(fk_id2))
                        .and(MY_TABLE.ID3.equal(fk_id3))
                .orderBy(MY_TABLE.ID.asc())
                .limit(limit)
                .fetchInto(MY_TABLE)
                .map(mapper());

我正在尝试编写一些代码,以允许我的查询采用三个可选 ID,例如我希望查询最终成为

select * from my_table where ID1=5 and ID2=6 and ID3=7 .... etc 

但是,我还想要能够排除任何 id 的选项

select * from my_table where ID2=6 and ID3=7 

select * from my_table where ID3=7

这个问题是第一个 "where" 子句属于 id one,其余的是 ands 所以如果我做了一个 if 语句并删除了 where 那么我将只剩下

List<MyTable> result = DSL.using(configuration())
                .select()
                .from(MY_TABLE)
                        .and(MY_TABLE.ID2.equal(fk_id2))
                        .and(MY_TABLE.ID3.equal(fk_id3))
                .orderBy(MY_TABLE.ID.asc())
                .limit(limit)
                .fetchInto(MY_TABLE)
                .map(mapper());

而且它不起作用。

我试图寻找类似 where id = * 的东西,其中 * 基本上没有过滤器,但我找不到类似的东西。

您要求的内容有时被称为 "SQL 'number' wildcarding" 或者至少您可以在网络上搜索评论。

SQL 不允许你写 "where id = *" 相反,如果你需要你的 DDL 保持静态,你可以通过像

这样的范围检查来模拟它
select * from table
  where
    (my_table.id1 >= fk_id1_low and my_table.id1 <= fk_id1_high) and
    (my_table.id2 >= fk_id2_low and my_table.id2 <= fk_id2_high) and
    (my_table.id3 >= fk_id3_low and my_table.id3 <= fk_id3_high)

所以现在你总共向查询传递了 6 个参数,如果你想对 id1 进行匹配,你需要将 fk_id1_low 和 fk_id1_high 都设置为你想要匹配的值.如果您不想与 id1 匹配,您可以将 fk_id1_low 设置为最小可能值,将 fk_id1_high 设置为最大可能值。您必须考虑这样做的一件事是数据库引擎将如何处理结果查询,因为可能会执行大量额外工作。

对于 JOOQ,另一个可能的答案是放弃流畅的界面,以便您可以使用 if..then 条件部分构建查询。

jOOQ 使写作 SQL 感觉就像是静态的、嵌入的 SQL。但事实并非如此。每个 jOOQ 查询都是一个由表达式树组成的动态 SQL 查询 - 你只是没有注意到它。

SelectWhereStep.where(Condition) 方法采用 Condition 参数,您不必将其与 WHERE 子句放在一起。您可以在查询之前构造它:

Condition condition = DSL.noCondition(); // Alternatively, use trueCondition()
if (something)
    condition = condition.and(MY_TABLE.ID1.equal(pk_id1));
if (somethingElse)
    condition = condition.and(MY_TABLE.ID2.equal(fk_id2));
if (somethingOther)
    condition = condition.and(MY_TABLE.ID3.equal(fk_id3));

您现在可以将其传递给您的查询:

List<MyTable> result = 
DSL.using(configuration())
   .select()
   .from(MY_TABLE)
   .where(condition)
   .orderBy(MY_TABLE.ID.asc())
   .limit(limit)
   .fetchInto(MY_TABLE)
   .map(mapper());

DSL中还有实用方法,如:

手册中也有记载:http://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql/

注意,通常没有必要直接引用 XYZStep 类型。 You should mostly be able to write dynamic SQL through more elegant ways, as I've shown in this blog post.