如何在 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
中还有实用方法,如:
DSL.condition(Map<Field<?>,?>)
从字段/值比较映射构建条件
DSL.condition(Record)
for using the Query By Example 模式
DSL.condition(Operator, Condition...)
or simply DSL.and(Condition...)
用于从数组(或集合)构造 AND
连接条件
手册中也有记载: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.
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
中还有实用方法,如:
DSL.condition(Map<Field<?>,?>)
从字段/值比较映射构建条件DSL.condition(Record)
for using the Query By Example 模式DSL.condition(Operator, Condition...)
or simplyDSL.and(Condition...)
用于从数组(或集合)构造AND
连接条件
手册中也有记载: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.