在更新语句中排除空列 - JOOQ

Posted

技术标签:

【中文标题】在更新语句中排除空列 - JOOQ【英文标题】:Exclude null columns in an update statement - JOOQ 【发布时间】:2021-12-17 19:23:11 【问题描述】:

我有一个 POJO,其中包含可以更新的字段。但有时只需要更新几个字段,其余字段为空。如何编写忽略空字段的更新语句?循环遍历未丢失的并动态添加到 set 语句或使用合并会更好吗?

我有以下疑问:

jooqService.using(txn)
        .update(USER_DETAILS)
        .set(USER_DETAILS.NAME, input.name)
        .set(USER_DETAILS.LAST_NAME, input.lastName)
        .set(USER_DETAILS.COURSES, input.courses)
        .set(USER_DETAILS.SCHOOL, input.school)
        .where(USER_DETAILS.ID.eq(input.id))
        .execute()

如果有更好的做法?

【问题讨论】:

【参考方案1】:

我不认识 Jooq,但看起来你可以简单地这样做:

val jooq = jooqService.using(txn).update(USER_DETAILS)
input.name.let jooq.set(USER_DETAILS.NAME, it)
input.lastName.let jooq.set(USER_DETAILS.LAST_NAME, it)

等等……

编辑:在我看来,像上面那样明确地映射这些字段是最清楚的,但你可以这样做:

val fields = new Object[] USER_DETAILS.NAME, USER_DETAILS.LAST_NAME
val values = new Object[] input.name, input.lastName
val jooq = jooqService.using(txn).update(USER_DETAILS)
values.forEachIndexed  i, value ->
    value.let jooq.set(fields[i], value)

您仍然需要明确且一致地枚举数组中的所有字段和值才能使其正常工作。在我看来,它的可读性较差且更容易出错。

【讨论】:

谢谢!但是由于以后可以添加更多的字段,所以我一直在寻找一种通用的方法来过滤掉空字段。【参考方案2】:

在 Java 中是这样的

var jooqQuery = jooqService.using(txn)
        .update(USER_DETAILS);

if (input.name != null) 
    jooqQuery.set(USER_DETAILS.NAME, input.name);

if (input.lastName != null) 
    jooqQuery.set(USER_DETAILS.LAST_NAME, input.lastName);


// ...

jooqQuery.where(USER_DETAILS.ID.eq(input.id))
        .execute();

【讨论】:

【参考方案3】:

另一种选择而不是编写此UPDATE 语句是使用UpdatableRecord

// Load a POJO into a record using a RecordUnmapper
UserDetailsRecord r =
jooqService.using(txn)
    .newRecord(USER_DETAILS, input)
    
(0 .. r.size() - 1).forEach  if (r[it] == null) r.changed(it, false) 
r.update();

您可能可以编写一个扩展函数以使其可用于全局的所有 jOOQ 记录,例如作为r.updateNonNulls()

【讨论】:

以上是关于在更新语句中排除空列 - JOOQ的主要内容,如果未能解决你的问题,请参考以下文章

如何查看 jOOQ 在编译时执行的 SQL 语句?

如何查看 jOOQ 执行的 SQL 语句?

仅在非空列上的 case 语句

使用JOOQ无法在SQLITE中更新表行

在 jOOq 中,为啥连接与语句构造高度耦合?

JOOQ 和 TimescaleDB - 如何在 JOOQ 中实现基本的 time_bucket 语句