【问题标题】:JOOQ: Dynamic join conditionsJOOQ:动态连接条件
【发布时间】:2018-04-09 20:31:46
【问题描述】:

我想在 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) 
}

我该怎么做?

【问题讨论】:

  • 对不起,我不确定动态部分应该在这里。我建议用一些细节编辑问题。当mychecktrue / false 时,所需的 SQL 查询是什么?你的问题越完整,答案就越好......
  • 你不能在if 中做select.whereselect.join 吗??

标签: java jooq


【解决方案1】:

有几种方法可以解决这个问题:

使用隐式连接

在相对简单的情况下,当可选连接遵循一对一关系时,您可以使用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 删除它们可能是错误,而且肯定是低效的)。

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

按照您的要求使用 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.*;

【讨论】:

  • 谢谢卢卡斯!你是对的,这两个查询很简单。但不幸的是,我不仅要检查 fooParam。 (感谢您的出色工作!Jooq 太棒了!)
  • @Luigi1982:谢谢你的好话。当然,我“害怕”您的示例可能会被简化,所以我想半连接解决方​​案最适合这里......
猜你喜欢
  • 2018-10-05
  • 2019-09-02
  • 2018-03-29
  • 2015-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 2020-06-12
相关资源
最近更新 更多