[英]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();
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
的解決方案相比,並非所有數據庫都識別EXISTS
或IN
語法中的半連接,因此可能無法以最佳方式運行此語句。
// 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.