且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用JOOQ在PostgreSQL中插入带有JSON列的可更新记录?

更新时间:2023-08-20 13:39:52

从jOOQ 3.5开始,您可以将自己的自定义数据类型绑定注册到代码生成器记录在这里:

Since jOOQ 3.5, you can register your own custom data type bindings to the code generator as is documented here:

http://www.jooq.org/doc/latest/manual/code-generation/custom-data-type-bindings

Converter $不同c $ c> 绑定 指示如何在jOOQ内的JDBC级别处理数据类型,而无需jOOQ了解您的实现。即,您不仅要定义如何在< T> < U> 类型( T =数据库类型, U =用户类型),但您也可以定义这些类型的方式:

Unlike a Converter, a Binding dictates how your data type is being handled at the JDBC level within jOOQ, without jOOQ knowing about your implementation. I.e., not only will you define how to convert between <T> and <U> types (T = database type, U = user type), but you will also be able to define how such types are:


  • 呈现为SQL

  • 绑定到PreparedStatements

  • 绑定到SQLOutput

  • 在CallableStatements中注册为OUT参数

  • 从ResultSets获取

  • 从SQLInput获取

  • 从CallableStatements获取为OUT参数

  • Rendered as SQL
  • Bound to PreparedStatements
  • Bound to SQLOutput
  • Registered in CallableStatements as OUT parameters
  • Fetched from ResultSets
  • Fetched from SQLInput
  • Fetched from CallableStatements as OUT parameters

示例 Binding 与Jackson一起用于生成 JsonNode 类型在这里给出:

An example Binding for use with Jackson to produce JsonNode types is given here:

public class PostgresJSONJacksonJsonNodeBinding 
implements Binding<Object, JsonNode> {

    @Override
    public Converter<Object, JsonNode> converter() {
        return new PostgresJSONJacksonJsonNodeConverter();
    }

    @Override
    public void sql(BindingSQLContext<JsonNode> ctx) throws SQLException {

        // This ::json cast is explicitly needed by PostgreSQL:
        ctx.render().visit(DSL.val(ctx.convert(converter()).value())).sql("::json");
    }

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

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

    @Override
    public void get(BindingGetResultSetContext<JsonNode> ctx) throws SQLException {
        ctx.convert(converter()).value(ctx.resultSet().getString(ctx.index()));
    }

    @Override
    public void get(BindingGetStatementContext<JsonNode> ctx) throws SQLException {
        ctx.convert(converter()).value(ctx.statement().getString(ctx.index()));
    }

    // The below methods aren't needed in PostgreSQL:

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

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

以及转换器上面使用的code>可以在这里看到:

public class PostgresJSONJacksonJsonNodeConverter 
implements Converter<Object, JsonNode> {
    @Override
    public JsonNode from(Object t) {
        try {
            return t == null 
              ? NullNode.instance 
              : new ObjectMapper().readTree(t + "");
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Object to(JsonNode u) {
        try {
            return u == null || u.equals(NullNode.instance) 
              ? null 
              : new ObjectMapper().writeValueAsString(u);
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

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

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

您现在可以通过代码生成器注册上述绑定配置:

You can now register the above binding via the code generator configuration:

<customType>
    <name>com.example.PostgresJSONJacksonJsonNodeBinding</name>
    <type>com.fasterxml.jackson.databind.JsonNode</type>
    <binding>com.example.PostgresJSONJacksonJsonNodeBinding</binding>
</customType>

<forcedType>
    <name>com.example.PostgresJSONJacksonJsonNodeBinding</name>
    <expression>my_schema\.table\.json_field</expression>
</forcedType>