微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

我在Is it possible to write a data type Converter to handle postgres JSON columns?中听到了答案
 实现nodeObject转换器.

然后我尝试使用可更新记录来插入记录,我得到了“org.jooq.exception.sqlDialectNotSupportedException:在方言POSTGRES中不支持类型类org.postgresql.util.PGobject”异常.

我怎么解决这个问题?

以下是我的代码

TableRecord r = create.newRecord(TABLE);
ObjectNode node = JsonNodeFactory.instance.objectNode();
r.setValue(TABLE.JSON_FIELD, node, new JsonObjectConverter());
r.store();

解决方法:

从jOOQ 3.5开始,您可以将自己的自定义数据类型绑定注册代码生成器,如下所示:

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

Converter不同,Binding规定了如何在jOOQ内的JDBC级别处理数据类型,而无需jOOQ了解您的实现.即,您不仅将定义如何在< T>之间进行转换.和< U>类型(T =数据库类型,U =用户类型),但您也可以定义这些类型的方式:

>呈现为sql
>绑定到PreparedStatements
>绑定到sqlOutput
>在CallableStatements中注册为OUT参数
>从ResultSet获取
>从sqlInput获取
>从CallableStatements获取为OUT参数

这里给出了一个与Jackson一起使用以生成JsonNode类型的示例:

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();
    }
}

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

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;
    }
}

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

<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>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐