【问题标题】:jOOQ 3.15 postgres complaining about jsonb types in generated sqljOOQ 3.15 postgres 抱怨生成的 sql 中的 jsonb 类型
【发布时间】:2021-11-20 21:15:42
【问题描述】:

从 3.14 -> 3.15.3 升级我的 jOOQ 版本后弹出以下运行时错误:

ERROR: column "old_values" is of type jsonb but expression is of type character varying

代码如下:

final String jsonChanges = gson.toJson(map);
final InsertOnDuplicateStep<TicketLogRecord> insertLogs =
                insertInto(LOG,
                           LOG.ID,
                           LOG.OLD_VERSION,
                           LOG.OLD_VALUES,
                           LOG.NEW_VALUES)
                .select(
                        select(field("to_update.id", UUID.class),
                                field("to_update.version", Integer.class),
                                val("{}", JsonElement.class),
                                val(jsonChanges, JsonElement.class),
)
final var countUpdated =
                with("to_update", "id", "version", "state_id").as(ids)
                                                                      .with("update_states").as(updateWhere.returning())
                                                                      .with("insert_logs").as(insertLogs.returning())
                                                                      .select(count().as("updated_count"))
                                                                      .from("to_update");
            return using(configuration)
                .fetchOne(countUpdated)
                .getValue("updated_count", Integer.class);

通过强制转换cast(val("{}", JsonElement.class), LOG.OLD_VALUES) 并在其下方的行上同样使用 NEW_VALUES 解决了该问题。但我很感兴趣,为什么在这两个次要版本之间会出现这个 SQL 生成问题?

谢谢

【问题讨论】:

    标签: jooq


    【解决方案1】:

    为什么会发生这种情况/“倒退”?

    这里的用法:

    val(jsonChanges, JsonElement.class)
    

    正在使用未记录的“功能”,该功能在某些情况下(并非总是)偶然发生。在您的情况下,它似乎对您有用。但是,只有SQLDataType 支持的类字面量才能传递给DSL.val(Object, Class) 之类的方法,所以这是有效的:

    field("to_update.version", Integer.class)
    

    但是传递JsonElement 不是。 jOOQ 不可能知道您打算如何将 JsonElement 值绑定到 JDBC 驱动程序。它可能起作用了,因为您在某处注册了Binding&lt;Object, JsonElement&gt;,并且由于该绑定(历史上)被添加到内部静态DataType 注册表中,查找JsonElement.class 的绑定有时会起作用。它可能不起作用的原因:

    • 注册Binding&lt;Object, JsonElement&gt;的类尚未加载
    • jOOQ 中的内部重构改变了其中一些未记录的查找行为

    这在 jOOQ 中绝对值得关注:

    • #12470 更好的 Javadoc
    • #12471 当用户尝试查找不受支持的类文字时记录警告

    如何解决?

    在您的特定情况下,您已经在 LOG.OLD_VALUES 中引用了 DataType&lt;JsonElement&gt;。您的演员可以工作,但更好的是,只需完全删除 JsonElement.class 文字并改为这样写:

    // Assuming your JSON library is Gson
    val(new JsonObject(), LOG.OLD_VALUES)
    

    这将从OLD_VALUES 列(包括其绑定)中获取DataType,并使用它来绑定JsonObject 值。

    【讨论】:

      猜你喜欢
      • 2021-03-07
      • 2019-08-03
      • 1970-01-01
      • 1970-01-01
      • 2015-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多