【问题标题】:jOOQ - Reusing SelectConditionStepjOOQ - 重用 SelectConditionStep
【发布时间】:2019-10-08 20:27:48
【问题描述】:

我有一些这样的代码:

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 的内部结构,这种重用是否应该避免。

【问题讨论】:

    标签: java sql jooq


    【解决方案1】:

    由于历史原因,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 变得复杂时,它们的组合性较差且不容易正确
    • 它们的可读性较差
    • 它们可能在次要版本之间存在二进制不兼容的更改

    我建议你改用functional approach to writing dynamic 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()方便的方法。

    See also this blog post for more insight on why not to reference the XYZStep types directly.

    【讨论】:

      猜你喜欢
      • 2021-11-11
      • 2019-08-07
      • 2012-05-02
      • 2022-01-08
      • 2023-01-18
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 2020-07-26
      相关资源
      最近更新 更多