首页 > 解决方案 > 在 JOOQ 中建立动态表连接

问题描述

我使用 JOOQ 作为 SQL 构建器工具,然后在 jdbcTemplate 中执行。我需要动态地将表连接添加到 from 子句。目前我正在这样做..

SelectJoinStep<?> selectClause = select(field("ColumnA"), field("ColumnB"))
.from(table("TableA"));

if(condition) {
  selectClause.join(table("TableB), JoinType.JOIN).on(field("columnA").eq(field("columnB")));
}

然后我将 select 子句与 where 子句结合起来。

org.jooq.Query ps = selectClause.where(whereClause);

这工作正常,但现在我想引入分页,所以我需要将所选字段换出一个简单的计数,如果我可以在这个计数查询中重用 from 子句会很好,但我不能因为 select 和 from 子句在同一个变量中。

更新..为什么我不能像这样动态地建立 from 子句......

    List<Field<?>> fields = new ArrayList<Field<?>>();
    fields.add(...);
    Table<?> from = table("TableA");
    if(condition) {
      from.join(table("TableB), JoinType.JOIN).on(field("columnA").eq(field("columnB")));
    }
org.jooq.Query ps = select(fields).from(from);

如果条件为真,表连接不会出现在生成的 SQL 中?

标签: javasqljooq

解决方案


将 jOOQ 用于动态 SQL 的最佳方法是功能性更强的方法。不要考虑在某些条件下“交换”部分查询。想想你的查询的哪些部分是由谁通过函数提供的?例如:

ResultQuery<?> query(
    Supplier<Collection<SelectField<?>>> select,
    boolean condition,
    boolean paginate
) {
    Condition whereClause = ...;
    Table<?> from = table("TableA");
    if (condition)
        from = from.join(table("TableB")).on(field("ColumnA").eq(field("ColumnB")));

    return select(select.get())
          .from(from)
          .where(whereClause)
          .limit(paginate ? 10 : Integer.MAX_VALUE); // Could be done differently
}

现在调用上面的:

query(() -> Arrays.asList(field("ColumnA"), field("ColumnB")), true, true);
query(() -> Arrays.asList(count()), true, false);

当然,另一种选择是使用窗口函数来计算该计数值,而不是运行两个查询:

count().over()

推荐阅读