jOOQ生成的Record类获取数据是否使用列索引,能否改用列名?
问题解答
1. jOOQ Record类默认获取数据的方式
jOOQ默认使用列索引从ResultSet中读取数据填充生成的Record类,该设计的初衷是最大化读取性能,避免按列名匹配的额外开销。
上述类型报错根因是:使用了TABLE.asterisk()作为returning的返回列,当底层表新增了生成Record时不存在的列后,select *返回的列顺序和数量与生成Record预期的列索引完全错位,导致原本是字符串类型的列被Byte类型的字段按索引读取,触发类型转换异常。
2. 切换为列名读取的方案
可以通过全局配置调整映射逻辑,开启按列名匹配的模式:
Settings settings = new Settings() .withUseColumnNamesForRecordTypeMapping(true); // 初始化DSLContext时传入该配置 DSLContext dsl = DSL.using(connection, dialect, settings);
开启该配置后,jOOQ会忽略ResultSet的列顺序,直接通过列名匹配对应Record字段,完美适配Schema迭代场景(加列、删列只要用到的字段存在就不会报错),仅会损失极少量可忽略的映射性能。
3. 生成代码与文档不一致的说明
官方文档展示的setter逻辑是简化的示例代码,实际3.14版本生成的Record使用索引调用set方法是性能优化的实现方式,该实现和运行时ResultSet的映射逻辑无关:运行时的字段映射是由Binding层控制的,不管生成的setter用索引还是列对象,开启列名匹配配置后都会按列名读取数据填充到对应字段,不存在功能冲突。
临时规避方案
如果不想修改全局配置,可以将returning(TABLE.asterisk())修改为显式指定需要返回的列,保证返回列的顺序和数量与生成Record的定义完全一致,即可避免索引错位问题:
jooq.insertInto(TABLE) .set(TABLE.COL, "ABC") .returning(TABLE.COL1, TABLE.COL2, TABLE.COL3) // 显式列出所有需要返回的列 .fetchOne();
内容的提问来源于stack exchange,提问作者Jens Møller
相关产品推荐
相关产品推荐

