You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免频繁使用val调用数据库表生成函数?

优化jOOQ表生成函数调用的冗余代码

问题场景

调用数据库some_table_generating_function函数时,为了生成返回Field<Array<UUID>>的查询,必须频繁使用DSL的val函数,导致代码冗余。以下是可正常运行但val调用过多的示例:

context
  .select()
  .from(
    select(
      // 需要查询的字段
    )
      .from(
        Public.SOME_TABLE_GENERATING_FUNCTION(
          `val`(someString.capitalise()),
          `val`(someInt),
          `val`(BigDecimal(someDecimalString)),
          `val`(someInt),
          `val`(BigDecimal(anotherDecimalString)),
          `val`(BigDecimal(yetAnotherDecimalString)),
          `val`(anotherInt),
          `val`(someLong),
          `val`(anotherLong),
          // 关键参数:需要传入uuid[]类型
          field(
            "ARRAY({0})::uuid[]",
            select(A_TABLE.UUID.cast(String::class.java))
              .from(A_TABLE)
              .innerJoin(ANOTHER_TABLE)
              .on(A_TABLE.UUID.eq(ANOTHER_TABLE.UUID))
              .where(
                // 额外条件
              )
          ) as Field<Array<UUID>>
        )
      )
      .join(THE_TABLE)
      .asTable("inner_query")
  )
  .where(
    // 额外条件
  )

优化方案

1. 用扩展函数简化val调用

给常用类型定义扩展函数,把val调用封装起来,减少重复代码:

// 定义全局扩展函数
fun <T> T.toField(): Field<T> = DSL.`val`(this)

// 调用示例
Public.SOME_TABLE_GENERATING_FUNCTION(
    someString.capitalise().toField(),
    someInt.toField(),
    BigDecimal(someDecimalString).toField(),
    // ...其他参数依次替换
)

2. 直接传入原始值(若代码生成器支持)

如果你的表生成函数是jOOQ代码生成器自动生成的,检查函数签名——很多情况下生成的函数支持直接接收原始类型参数,jOOQ会自动帮你绑定为Field,不需要显式调用val。直接写成这样即可:

Public.SOME_TABLE_GENERATING_FUNCTION(
    someString.capitalise(),
    someInt,
    BigDecimal(someDecimalString),
    // ...其他参数直接传原始值
)

3. 封装参数为数据类批量映射

如果参数数量较多,把参数封装成数据类,再写一个映射方法批量转换为Field列表,代码更整洁:

// 定义参数数据类
data class FuncParams(
    val capitalisedStr: String,
    val int1: Int,
    val dec1: BigDecimal,
    val int2: Int,
    val dec2: BigDecimal,
    val dec3: BigDecimal,
    val int3: Int,
    val long1: Long,
    val long2: Long,
    val uuidArray: Field<Array<UUID>>
)

// 数据类转函数参数的方法
fun FuncParams.toArgs(): Array<Field<*>> = arrayOf(
    `val`(capitalisedStr),
    `val`(int1),
    `val`(dec1),
    `val`(int2),
    `val`(dec2),
    `val`(dec3),
    `val`(int3),
    `val`(long1),
    `val`(long2),
    uuidArray
)

// 使用示例
val params = FuncParams(
    someString.capitalise(),
    someInt,
    BigDecimal(someDecimalString),
    someInt,
    BigDecimal(anotherDecimalString),
    BigDecimal(yetAnotherDecimalString),
    anotherInt,
    someLong,
    anotherLong,
    // 优化后的UUID数组参数
    DSL.array(
        select(A_TABLE.UUID)
            .from(A_TABLE)
            .innerJoin(ANOTHER_TABLE)
            .on(A_TABLE.UUID.eq(ANOTHER_TABLE.UUID))
            .where(/* 条件 */)
    ) as Field<Array<UUID>>
)

Public.SOME_TABLE_GENERATING_FUNCTION(*params.toArgs())

4. 简化UUID数组参数的写法

原代码中手动拼接SQL生成UUID数组的方式可以用jOOQ的DSL.array方法替代,避免原生SQL拼接,更符合jOOQ的风格:

DSL.array(
    select(A_TABLE.UUID)
        .from(A_TABLE)
        .innerJoin(ANOTHER_TABLE)
        .on(A_TABLE.UUID.eq(ANOTHER_TABLE.UUID))
        .where(/* 额外条件 */)
) as Field<Array<UUID>>

如果使用的jOOQ版本足够新,甚至不需要显式强转,array方法会自动推断类型。

内容的提问来源于stack exchange,提问作者Buğra Ekuklu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 08:25:27