如何在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 均失败:
- 使用
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
- 使用
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) }但该方式不如直接选择所有字段简洁。
其他可行方案:
- 同步jOOQ生成代码与数据库schema,从根源避免列不匹配导致的类型转换错误。
- 显式列出所有需要的字段,完全控制列映射:
context.select( MY_TABLE.ID, MY_TABLE.NAME, // 其他字段... ) .from(MY_TABLE) .fetchInto(MY_TABLE)
内容的提问来源于stack exchange,提问作者PunDefeated
相关产品推荐
相关产品推荐

