如何避免频繁使用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
相关产品推荐
相关产品推荐

