JOOQ:动态连接条件

时间:2017-10-28 10:09:10

标签: java jooq

我想在JOOQ中通过选择创建条件。因为在我的情况下,我想声明一个动态查询并检查TABLE_C.FIELDC是否仅在我需要时包含“foo”...

示例

SelectFinalStep select = create.select().from(TABLEA);

if (isFooSearched) { 
   query.addCondition( <JOIN> and <CONTAINS> like first example) 
}

:

我该怎么做?

1 个答案:

答案 0 :(得分:2)

基本上有三种方法可以解决这个问题:

使用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上获得任何重复行(使用{{1删除它们)可能是错的,当然效率低下。)

附注:并非所有数据库都使用DISTINCTEXISTS语法识别半连接,因此与基于IN的解决方案相比,可能无法以最佳方式运行此语句。

按要求使用INNER JOIN

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(); 使用在你的联合变体查询中可能是正确的这一事实,但它(可能)会伤害你(&#34;默认& #34;查询变体,所以或许,将这个变成一个动态查询可能会有点过分。

...因此

使用两个不同的查询

根据我的喜好,这两个查询很简单,可以允许一些重复,只需根据标志运行两个不同的查询:

DISTINCT

旁注

所有解决方案都假设您的代码中包含以下静态导入:

if (isFooSearched)
    create.select().from(TABLE_A) /* joins or semi joins here */ .fetch();
else
    create.select().from(TABLE_A).fetch();