Jooq- 将字段更新为 NULL 使其成为 "null" 而不是 NULL

Jooq- Updating a field to NULL makes it "null" and not NULL

所以这是我以前在 jooq 3.11 中工作的查询。

我正在更新一个 JSON 字段,但是它使用 JsonBinding 映射到我的模型中的一个字符串,我将在下面 post

        dsl.update(TASK)
            .set(TASK.JSON_SOLUTION, (String) null).            
        .where(TASK.TENANT.eq(getCurrentTenant()))
        .and(TASK.TASK_TEMPLATE_ID.in(taskTemplateIds));execute()

升级到 jooq 3.13.2 后现在不再有效。我还必须将我的 sql 方言更改为 mysql,即使我正在使用 mysql 5_7 数据库,这可能是问题所在?

这个我也试过了,还是一样

        dsl.update(TASK)
            .setNull(TASK.JSON_SOLUTION).            
         .where(TASK.TENANT.eq(getCurrentTenant()))
        .and(TASK.TASK_TEMPLATE_ID.in(taskTemplateIds));execute()

JsonBinding.class

public class JsonBinding implements Binding<JSON, String> {

  @Override
  public Converter<JSON, String> converter() {
    return new JsonConverter();
  }

  @Override
  public void sql(BindingSQLContext<String> bindingSQLContext) {
    if (bindingSQLContext.render().paramType() == ParamType.INLINED) {
      bindingSQLContext
          .render()
          .visit(DSL.inline(bindingSQLContext.convert(converter()).value()))
          .sql("::json");
    } else {
      bindingSQLContext.render().sql("?");
    }
  }

  @Override
  public void register(BindingRegisterContext<String> bindingRegisterContext) throws SQLException {
    bindingRegisterContext
        .statement()
        .registerOutParameter(bindingRegisterContext.index(), Types.VARCHAR);
  }

  @Override
  public void set(BindingSetStatementContext<String> bindingSetStatementContext)
      throws SQLException {
    bindingSetStatementContext
        .statement()
        .setString(
            bindingSetStatementContext.index(),
            Objects.toString(bindingSetStatementContext.convert(converter()).value(), null));
  }

  @Override
  public void set(BindingSetSQLOutputContext<String> bindingSetSQLOutputContext)
      throws SQLException {
    throw new SQLFeatureNotSupportedException();
  }

  @Override
  public void get(BindingGetResultSetContext<String> bindingGetResultSetContext)
      throws SQLException {
    bindingGetResultSetContext
        .convert(converter())
        .value(
            JSON.valueOf(
                bindingGetResultSetContext
                    .resultSet()
                    .getString(bindingGetResultSetContext.index())));
  }

  @Override
  public void get(BindingGetStatementContext<String> bindingGetStatementContext)
      throws SQLException {
    bindingGetStatementContext
        .convert(converter())
        .value(
            JSON.valueOf(
                bindingGetStatementContext
                    .statement()
                    .getString(bindingGetStatementContext.index())));
  }

  @Override
  public void get(BindingGetSQLInputContext<String> bindingGetSQLInputContext) throws SQLException {
    throw new SQLFeatureNotSupportedException();
  }
}

JsonConverter.class

public class JsonConverter implements Converter<JSON, String> {

  @Override
  public String from(JSON object) {
    return object != null ? object.toString() : null;
  }

  @Override
  public JSON to(String string) {
    return JSON.valueOf(string);
  }

  @Override
  public Class<JSON> fromType() {
    return JSON.class;
  }

  @Override
  public Class<String> toType() {
    return String.class;
  }
}

这是使用 .setNull()

运行的查询 jooq
update `tasks_service`.`task` set `tasks_service`.`task`.`json_solution` = 'null'::json where (`tasks_service`.`task`.`tenant` = 'skynet' and `tasks_service`.`task`.`task_template_id` in ('55', '33'))

在 jooq 3.11 升级之前,查询结果如下

update `tasks_service`.`task` set `tasks_service`.`task`.`json_solution` = null::json where (`tasks_service`.`task`.`tenant` = 'skynet' and `tasks_service`.`task`.`task_template_id` in ('55', '33'))

所以在设置 'json_solution' = null 之前和升级之后它似乎设置为 'json_solution' = 'null'

不太清楚为什么会这样?

编辑:据我所知,这似乎完全来自 JOOQ 的升级,而不是 sql-方言。使用 Jooq 3.11.5,同时使用 mysql 和 mysql_5_7 作为方言,如果我将 JOOQ 升级到 3.13.2,查询将构建为 set 'json_solution' = null它的集合 'json_solution' = 'null'

这个怪癖似乎也只发生在 JSON 字段上,我尝试在同一个 table 上将另一个 varchar String 字段设置为 null,我得到了正确的设置“field_name' = null

问题可能出在我的 JsonBinding/JsonConverter 上?我不得不稍微修改它以使用 JOOQ 中的新 JSON 对象,因为之前 JOOQ 将 JSON 映射为 Object

JSON.valueOf(null) 对比 (JSON) null

答案在org.jooq.JSON的Javadoc中:

A CAST(NULL AS JSON) value is represented by a null reference of type JSON, not as data() == null. This is consistent with jOOQ's general way of returning NULL from Result and Record methods.

所以,错误在于JsonConverterJSON.valueOf()的用法。改为这样写:

  public JSON to(String string) {
    return string == null ? null : JSON.valueOf(string);
  }

或者,只需使用 Converter.ofNullable(),它会为您处理 null-to-null 映射:

Converter<JSON, String> converter = Converter.ofNullable(
  JSON.class,
  String.class,
  JSON::data,
  JSON::json
);

关于使用 Binding

的附注

你真的不再需要绑定了,现在 jOOQ 原生支持 JSON 类型。如果您想将 JSON 转换为 String,您的 Converter 就足够了。