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

如何在jOOQ中用row或.fields替代asterisk()?解决列匹配异常

问题描述

当生成的jOOQ代码与数据库schema不完全匹配时,使用select(alias.asterisk())执行查询会抛出类型转换错误:

org.postgresql.util.PSQLException: Bad value for type long : 633473bd597addd971f5b27e
    at org.postgresql.jdbc.PgResultSet.toLong(PgResultSet.java:3328)
    at org.postgresql.jdbc.PgResultSet.getLong(PgResultSet.java:2540)
    at com.zaxxer.hikari.pool.HikariProxyResultSet.getLong(HikariProxyResultSet.java)
    at org.jooq.tools.jdbc.DefaultResultSet.getLong(DefaultResultSet.java:149)
    at org.jooq.impl.CursorImpl$CursorResultSet.getLong(CursorImpl.java:562)
    at org.jooq.impl.DefaultBinding$DefaultLongBinding.get0(DefaultBinding.java:3071)
    at org.jooq.impl.DefaultBinding$DefaultLongBinding.get0(DefaultBinding.java:3032)
    at org.jooq.impl.DefaultBinding$InternalBinding.get(DefaultBinding.java:1071)
    at org.jooq.impl.CursorImpl$CursorRecordInitialiser.setValue(CursorImpl.java:1581)
    at org.jooq.impl.CursorImpl$CursorRecordInitialiser.apply(CursorImpl.java:1517)
    at org.jooq.impl.CursorImpl$CursorRecordInitialiser.apply(CursorImpl.java:1432)
    at org.jooq.impl.RecordDelegate.operate(RecordDelegate.java:144)
    at org.jooq.impl.CursorImpl$CursorIterator.fetchNext(CursorImpl.java:1389)
    at org.jooq.impl.CursorImpl$CursorIterator.hasNext(CursorImpl.java:1365)
    at org.jooq.impl.CursorImpl.fetchNext(CursorImpl.java:173)
    at org.jooq.impl.AbstractCursor.fetch(AbstractCursor.java:177)
    at org.jooq.impl.AbstractCursor.fetch(AbstractCursor.java:88)
    at org.jooq.impl.AbstractResultQuery.execute(AbstractResultQuery.java:265)
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:357)
    at org.jooq.impl.AbstractResultQuery.fetch(AbstractResultQuery.java:290)
    at org.jooq.impl.SelectImpl.fetch(SelectImpl.java:2838)

直接使用.asterisk()(非别名表)查询正常,但尝试两种 workaround 均失败:

  1. 使用TABLE.fields()出现编译错误:
context
    .select(MY_TABLE.fields())
    ...
None of the following functions can be called with the arguments supplied.
select((MutableCollection<out SelectFieldOrAsterisk!>..Collection<SelectFieldOrAsterisk!>?)) defined in org.jooq.DSLContext
select(vararg SelectFieldOrAsterisk!) defined in org.jooq.DSLContext
select(SelectField<TypeVariable(T1)!>!)   where T1 = TypeVariable(T1) for   fun <T1 : Any!> select(field1: SelectField<T1!>!): SelectSelectStep<Record1<T1!>!> defined in org.jooq.DSLContext
  1. 使用fieldsRow()查询返回全null值:
private companion object {
    private const val MY_TABLE_ALIAS = "table"

    private val MY_TABLE = TABLE
        .`as`(MY_TABLE_ALIAS)
}
...
context
    .select(MY_TABLE.fieldsRow())
    .from(MY_TABLE)
    .fetchInto(MY_TABLE)
    // values are all null in the toApi call
    .map(AvailabilityRegionsRecord::toApi)

使用环境:PostgreSQL方言,jOOQ版本3.18.3

解决方法
  • 修正TABLE.fields()的调用方式:
    MY_TABLE.fields()返回Field[],但jOOQ的select()需要可变参数。在Kotlin中需用*操作符将数组转为可变参数,正确写法:

    context.select(*MY_TABLE.fields())
           .from(MY_TABLE)
           .fetchInto(MY_TABLE)
    

    此方式能正确选择别名表的所有字段,避免列顺序或类型不匹配问题。

  • 解决fieldsRow()返回null的问题:
    select(MY_TABLE.fieldsRow())返回的是单行类型结果,fetchInto(MY_TABLE)无法直接将行类型映射为普通记录。若要使用此方式,需先提取行内字段:

    context.select(MY_TABLE.fieldsRow())
           .from(MY_TABLE)
           .fetch { it.getValue(MY_TABLE.fieldsRow()).into(MY_TABLE) }
    

    但该方式不如直接选择所有字段简洁。

  • 其他可行方案:

    1. 同步jOOQ生成代码与数据库schema,从根源避免列不匹配导致的类型转换错误。
    2. 显式列出所有需要的字段,完全控制列映射:
      context.select(
          MY_TABLE.ID,
          MY_TABLE.NAME,
          // 其他字段...
      )
      .from(MY_TABLE)
      .fetchInto(MY_TABLE)
      

内容的提问来源于stack exchange,提问作者PunDefeated

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 14:35:30