jOOQ中Record.from(POJO)未更新formula字段的问题排查
问题描述
我有一个jOOQ生成的POJO类,希望将其值复制到对应的jOOQ Record中,伪代码如下:
var record = dslContext.fetchOptional(tbl, pkField.eq(pkValue)).get() record.from(dto); record.store();
其中DTO与Record的差异在于formula字段:Record中该字段值为字符串"true",DTO中是其他值,但调用record.from(dto)后,Record的formula字段仍保留旧值,未被更新。
跟踪代码发现,在AbstractRecord.from0方法中,调用:
Tools.configuration(this).recordUnmapperProvider().provide(source.getClass(), (FieldsImpl) fields.fields).unmap(prepareArrayOrIterableForUnmap(source, targetIndexMapping))
返回的对象中,该字段值被重置为Record原有值,而非DTO中的值。
另外发现Tools类的getInstanceMethods方法返回的方法集用于确定获取字段值的getter方法,由于存在is_formula字段,推测isFormula() getter会先于formula()被调用,导致用isFormula()的返回值设置record.formula。
请问我的更新方式是否有误?
问题根源
这是jOOQ映射POJO到Record时的getter方法优先级问题。jOOQ默认优先识别isXxx()形式的getter(对应布尔类型字段),如果DTO中同时存在isFormula()和formula()两个方法,jOOQ会优先使用isFormula()的返回值映射formula字段。
若isFormula()返回布尔值,而formula字段在Record中是字符串类型,jOOQ会自动将布尔值转为"true"/"false",直接覆盖DTO中formula()方法的真实值,最终导致Record的formula字段未按预期更新。
解决方法
1. 统一DTO的getter方法
如果formula字段是字符串类型,删除DTO中的isFormula()方法,只保留getFormula()(或formula(),依命名规范而定),确保jOOQ只读取正确的字段值。
2. 自定义RecordUnmapper
若无法修改DTO方法,可自定义RecordUnmapper指定字段映射逻辑:
dslContext.configuration().setRecordUnmapperProvider(ctx -> new DefaultRecordUnmapper<>(ctx) { @Override public <E> Object[] unmap(E source) { Object[] result = super.unmap(source); // 手动设置formula字段值 if (source instanceof YourDTO dto) { int index = ctx.fields().indexOf(YOUR_TABLE.FORMULA); if (index != -1) { result[index] = dto.getFormula(); } } return result; } } );
3. 手动赋值单个字段
绕过自动映射,手动更新特定字段:
var record = dslContext.fetchOptional(tbl, pkField.eq(pkValue)).get(); record.from(dto); // 手动覆盖formula字段 record.set(YOUR_TABLE.FORMULA, dto.getFormula()); record.store();
更新方式说明
你的基础更新方式本身没有错误,问题出在jOOQ自动映射的getter优先级逻辑上。通过上述方法修正映射逻辑后,即可正常更新formula字段。
内容的提问来源于stack exchange,提问作者Mahdi

