JOOQ抛出IllegalArgumentException:字段不在Row中问题求助
JOOQ字段获取异常问题分析与解决
问题场景
执行JOOQ查询时,明明目标字段存在于数据库表中,却抛出字段不在Row中的IllegalArgumentException,查询结果显示数据正常,但无法提取单个字段值。
代码示例
Integer id = 5; if (id != null) { final var configurationResult = context.select(Configuration.CONFIGURATION) .from(Configuration.CONFIGURATION) .where(Configuration.CONFIGURATION.DEVICE_ID.eq(id)) .fetch(); configurationResult.forEach(configuration -> { final var minTemp = configuration.getValue(Configuration.CONFIGURATION.MINIMUM_TEMPERATURE_THRESHOLD); System.out.println("MinimumTemp is: " + minTemp); }); }
异常信息
Exception in thread "" java.lang.IllegalArgumentException: Field ("public"."configuration"."minimum_temperature_threshold") is not contained in Row (row ( "public"."configuration"."configuration_id", "public"."configuration"."minimum_temperature_threshold", "public"."configuration"."maximum_temperature_threshold", "public"."configuration"."ideal_temperature", "public"."configuration"."minimum_ph_threshold", "public"."configuration"."maximum_ph_threshold", "public"."configuration"."ideal_ph", "public"."configuration"."light_on_time", "public"."configuration"."light_off_time", "public"."configuration"."update_time", "public"."configuration"."device_id" ))
查询结果
|configuration | |(6, 22, 28, 24, 7, 9, 8, 2023-05-15T18:00, 2023...|
原因分析
核心问题在于查询时的字段选择方式:
- 代码中使用了
select(Configuration.CONFIGURATION),这会将整个表的行记录作为一个单独的字段返回,而不是展开所有字段。 - 此时查询结果的结构是:每个结果对象包含一个名为
configuration的Row类型字段,该Row字段内部才包含minimum_temperature_threshold等所有子字段。 - 直接调用
configuration.getValue(单个字段)时,JOOQ会在当前结果的顶级字段中查找目标字段,自然找不到,因为目标字段嵌套在内部Row里。
解决方向
提供两种可行的修正方案:
方案1:选择所有字段(推荐)
将查询语句改为使用selectFrom,直接返回包含所有字段的Record对象,这样可以直接提取单个字段:
final var configurationResult = context.selectFrom(Configuration.CONFIGURATION) .where(Configuration.CONFIGURATION.DEVICE_ID.eq(id)) .fetch();
或者显式选择所有字段:
final var configurationResult = context.select(Configuration.CONFIGURATION.fields()) .from(Configuration.CONFIGURATION) .where(Configuration.CONFIGURATION.DEVICE_ID.eq(id)) .fetch();
方案2:从嵌套Row中提取字段
如果需要保留原有的select(Configuration.CONFIGURATION)写法,需要先获取外层的Row字段,再从中提取目标子字段:
configurationResult.forEach(configuration -> { // 先获取整个行对象,再从中提取目标字段 final var configRow = configuration.getValue(Configuration.CONFIGURATION); final var minTemp = configRow.getValue(Configuration.CONFIGURATION.MINIMUM_TEMPERATURE_THRESHOLD); System.out.println("MinimumTemp is: " + minTemp); });
内容的提问来源于stack exchange,提问作者Damien Cooke
相关产品推荐
相关产品推荐

