JOOQ编写update语句时如何排除null值字段?有何最优实践?
问题解答
两种方案对比
优先选择动态拼接非空字段的实现方案,和coalesce函数方案的对比如下:
- 动态拼接方案:生成的SQL仅包含需要更新的字段,不会触发数据库不必要的字段写入、索引更新,执行性能更高,也支持主动把字段更新为null的业务场景,仅需在拼接时做特殊标记即可。
- coalesce函数方案:SQL结构固定,但即使字段不需要更新,数据库也会执行字段赋值逻辑,有额外性能开销,且无法支持主动将字段设为null的需求,仅适合SQL语句必须固定的特殊场景。
jOOQ场景下的最优实现
jOOQ官方已经提供了原生的忽略null值更新的能力,不需要手动写字段非空判断,也不需要拼接SQL:
方案1:使用setIfNotNull方法(jOOQ 3.14及以上版本)
直接替换原代码中的set为setIfNotNull即可,方法会自动判断值为null的字段不加入SET语句:
jooqService.using(txn) .update(USER_DETAILS) .setIfNotNull(USER_DETAILS.NAME, input.name) .setIfNotNull(USER_DETAILS.LAST_NAME, input.lastName) .setIfNotNull(USER_DETAILS.COURSES, input.courses) .setIfNotNull(USER_DETAILS.SCHOOL, input.school) .where(USER_DETAILS.ID.eq(input.id)) .execute()
方案2:Record批量更新(适合字段多的场景)
如果POJO字段非常多,逐个写set语句太繁琐,可以将POJO转换为对应表的UpdatableRecord,自动过滤null字段更新:
USER_DETAILSRecord record = jooqService.using(txn).newRecord(USER_DETAILS, input); // 把值为null的字段标记为不需要更新 record.resetChangedOnNull(); record.setId(input.id); record.update();
低版本jOOQ兼容方案
如果使用的jOOQ版本低于3.14,没有原生setIfNotNull方法,可以自行封装简易工具方法实现相同逻辑:
public <T> UpdateSetStep<?> setIfNotNull(UpdateSetStep<?> step, Field<T> field, T value) { if (value != null) { return step.set(field, value); } return step; }
调用时链式调用该方法即可。
内容的提问来源于stack exchange,提问作者NoraL
相关产品推荐
相关产品推荐

