我想从 JOOQ 中的 select 创建 条件 。因为在我的情况下,我想声明一个动态查询并仅在需要时检查 TABLE_C.FIELDC 是否包含“foo”...
示例 :
create.select().from(TABLE_A).join(TABLE_B).onKey(Keys.FK_TABLEA_TABLEB)
.join(TABLE_C).onKey(Keys.FK_TABLEB_TABLEC)
.where(TABLE_C.FIELDC.containsIgnoreCase("foo");
至:
SelectFinalStep select = create.select().from(TABLEA);
if (isFooSearched) {
query.addCondition( <JOIN> and <CONTAINS> like first example)
}
我怎样才能做到这一点?
最佳答案
有几种方法可以解决这个问题:
使用隐式连接
在相对简单的情况下,当可选连接遵循一对一关系时,您可以使用 implicit join(如果您使用的是代码生成器):
create.select()
.from(TABLE_A)
.join(TABLE_B).onKey(Keys.FK_TABLEA_TABLEB)
.where(isFooSearched
? TABLE_B.tableC().FIELDC.containsIgnoreCase("foo")
: noCondition())
.fetch();
使用 SEMI JOIN 而不是 INNER JOIN,这使得动态 SQL 更容易create.select()
.from(TABLE_A)
.where(
isFooSearched
? TABLE_A.TABLE_B_ID.in(
select(TABLE_B.ID)
.from(TABLE_B)
.join(TABLE_C).onKey(FK_TABLEB_TABLEC)
.where(TABLE_C.FIELDC.containsIgnoreCase("foo"))
)
: trueCondition())
.fetch();
请注意,在这种情况下,半连接在形式上也比内部连接更正确,因为对于多对多关系中的任何匹配项,您不会在 TABLE_A
上获得任何重复行(用 DISTINCT
删除它们可能是错误的,而且效率肯定很低)。旁注:并非所有数据库都识别
EXISTS
或 IN
语法中的半连接,因此与基于 JOIN
的解决方案相比,可能无法以最佳方式运行此语句。按照您的要求使用 INNER JOIN
// I'm assuming DISTINCT is required here, as you
// - are not interested in TABLE_B and TABLE_C results (semi join semantics)
// - do not want any duplicate TABLE_A values
create.selectDistinct(TABLE_A.fields())
.from(
isFooSearched
? TABLE_A
.join(TABLE_B).onKey(FK_TABLEA_TABLEB)
.join(TABLE_C).onKey(FK_TABLEB_TABLEC)
)
: TABLE_A)
.where(
isFooSearched
? TABLE_C.FIELDC.containsIgnoreCase("foo")
: trueCondition())
.fetch();
我在这里做了一些假设,包括这样一个事实,即 DISTINCT
的用法在您加入的查询变体上可能是正确的,但它(可能)在您的“默认”查询变体上伤害了您,所以也许,把它变成一个单个动态查询可能有点矫枉过正。因此...
使用两个不同的查询
根据我的口味,这两个查询足够简单,可以允许一些重复,只需根据标志运行两个不同的查询:
if (isFooSearched)
create.select().from(TABLE_A) /* joins or semi joins here */ .fetch();
else
create.select().from(TABLE_A).fetch();
边注所有解决方案都假设您的代码中有这些静态导入:
import static org.jooq.impl.DSL.*;
关于java - JOOQ:动态加入条件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46988529/