簡體   English   中英

JOOQ:動態加入條件

[英]JOOQ: Dynamic join conditions

我想從 JOOQ 中的這個選擇創建條件 因為在我的情況下,我想聲明一個動態查詢並僅在需要時檢查 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) 
}

我該怎么做?

有幾種方法可以解決這個問題:

使用隱式連接

在相對簡單的情況下,當可選連接遵循一對一關系時,您可以使用隱式連接(如果您使用的是代碼生成器):

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.*;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM