首页 > 解决方案 > jOOQ - 重用 SelectConditionStep

问题描述

我有一些这样的代码:

var step =
    db.select(T1.C1).
        from(T1).
        where(T1.C2.eq(v1));

var result = step.
    and(T1.C3.eq(v2)).
    fetchOne();

if(result == null) 
    result = step.
        and(T1.C3.eq(v3)).
        fetchOne();

它可以正常工作,但我想知道由于 jOOQ 的内部结构,这种重用是否可以避免。

标签: javasqljooq

解决方案


由于历史原因,DSL API 的某些元素是可变的,这意味着您不应在代码中重用对中间“步骤”类型的任何引用。这在每个“步骤”类型的 Javadoc 中都有提及:

直接从客户端代码引用 XYZ*Step 类型

通常不建议直接从客户端代码引用任何 XYZ*Step 类型,或者将它们分配给局部变量。在编写动态 SQL 时,动态创建语句的组件并将它们静态传递给 DSL API 通常是更好的选择。有关详细信息,请参阅手册中有关动态 SQL 的部分:https ://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql 。

直接引用 XYZ*Step 类型的缺点:

  • 他们在可变实现上运行(从 jOOQ 3.x 开始)
  • 当动态 SQL 变得复杂时,它们的组合性较差且不容易正确
  • 它们的可读性较差
  • 它们可能在次要版本之间具有二进制不兼容的更改

我建议您采用函数式方法来编写动态 SQL,而不是:

Select<Result1<Integer>> fetchOne(Condition condition) {
    return db.select(T1.C1)
             .from(T1)
             .where(T1.C2.eq(v1))
             .and(condition)
             .fetchOne();
}

var result = fetchOne(T1.C3.eq(v2));

if (result == null)
    result = fetchOne(T1.C3.eq(v3));

或者,在 SQL 中执行所有操作以防止额外的往返:

var result =
db.select(T1.C1)
  .from(T1)
  .where(T1.C2.eq(v1))
  .and(T1.C3.in(v2, v3))
  .orderBy(T1.C3.sortAsc(v2, v3))
  .limit(1)
  .fetchOne()

这是Field.sortAsc()使用方便的方法。

另请参阅此博客文章,以更深入地了解为什么不XYZStep直接引用这些类型。


推荐阅读