我想从 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 删除它们可能是错误的,而且效率肯定很低)。
旁注:并非所有数据库都识别 EXISTSIN 语法中的半连接,因此与基于 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/

10-11 22:25
查看更多