[英]JOOQ: Dynamic join conditions
I would like to create conditions from this select in JOOQ.我想从 JOOQ 中的这个选择创建条件。 Because in my case I want to declare a dynamic query and check if TABLE_C.FIELDC contains "foo" only when I need...
因为在我的情况下,我想声明一个动态查询并仅在需要时检查 TABLE_C.FIELDC 是否包含“foo”...
Example :示例:
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");
to:到:
SelectFinalStep select = create.select().from(TABLEA);
if (isFooSearched) {
query.addCondition( <JOIN> and <CONTAINS> like first example)
}
How can I do this?我该怎么做?
There are several ways to solve this:有几种方法可以解决这个问题:
In relatively simple cases, when the optional join follows a to-one relationship, you may be able to use an implicit join (if you're using the code generator):在相对简单的情况下,当可选连接遵循一对一关系时,您可以使用隐式连接(如果您使用的是代码生成器):
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();
Note that a semi join is also more formally correct in this case than an inner join, as you will not get any duplicate rows on TABLE_A
for any matches in to-many relationships (removing them with DISTINCT
might be wrong and certainly is inefficient).请注意,在这种情况下,半连接在形式上也比内部连接更正确,因为对于多对多关系中的任何匹配,您不会在
TABLE_A
上获得任何重复行(用DISTINCT
删除它们可能是错误的,而且肯定是低效的)。
Side-note: Not all databases recognise semi-joins in EXISTS
or IN
syntax, and may thus not optimally run this statement, compared to a JOIN
based solution.旁注:与基于
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();
I've mad a few assumptions here, including the fact that DISTINCT
usage could be correct on your joined variant of the query, but it is hurting you (probably) on your "default" query variant, so perhaps, shoe horning this into a single dynamic query might be overkill.我在这里做了一些假设,包括
DISTINCT
用法在您的查询的联接变体上可能是正确的这一事实,但它在您的“默认”查询变体上(可能)伤害了您,所以也许,把它变成一个单个动态查询可能有点矫枉过正。
Thus...因此...
For my taste, the two queries are simple enough to allow for some duplication and simply run two different queries depending on the flag:根据我的口味,这两个查询足够简单,可以允许一些重复,只需根据标志运行两个不同的查询:
if (isFooSearched)
create.select().from(TABLE_A) /* joins or semi joins here */ .fetch();
else
create.select().from(TABLE_A).fetch();
All solutions are assuming you have these static imports in your code:所有解决方案都假设您的代码中有这些静态导入:
import static org.jooq.impl.DSL.*;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.