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

标签 java sql postgresql postgresql-9.3 jooq

我遵循了Is it possible to write a data type Converter to handle postgres JSON columns?中的答案 实现 nodeObject 转换器。

然后我尝试使用可更新的记录来插入记录,我得到了 “org.jooq.exception.SQLDialectNotSupportedException: Type class org.postgresql.util.PGobject is not supported in dialect POSTGRES”异常。

我该如何解决这个问题?

以下是我的代码:

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

最佳答案

当前的 jOOQ 版本

jOOQ 原生支持 JSONJSONB数据类型,因此您无需执行任何特定操作。

历史答案

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

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

不同于 Converter , 一个 Binding 指示如何在 jOOQ 中的 JDBC 级别处理你的数据类型,而 jOOQ 不知道你的实现。即,您不仅会定义如何在 <T> 之间进行转换和 <U>类型(T = 数据库类型,U = 用户类型),但您还可以定义此类类型:

  • 呈现为 SQL
  • 绑定(bind)到 PreparedStatements
  • 绑定(bind)到 SQLOutput
  • 在 CallableStatements 中注册为 OUT 参数
  • 从结果集中获取
  • 从 SQLInput 中获取
  • 作为 OUT 参数从 CallableStatements 获取

一个例子 Binding与 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();
    }
}

还有 Converter上面使用的可以在这里看到:

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

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

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

关于java - 如何使用 JOOQ 在 PostgreSQL 中插入带有 JSON 列的可更新记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27044702/

相关文章:

java - JPA,Postgresql和SQL INSERT语句:UTC时间戳无法正常工作

完全写入文件后压缩文件的Java代码

php - 检查字符串是否在 MySQL 字段值中

mysql - 数据库列 int 限制

mysql - SQL 查询 : retrieve existing dates period with overlap

c - 这是逻辑错误还是发生了什么? foreach 的问题

java - 如何在java中调用R的auto.Arima函数并存储预测结果?

java - 如何使用 apache poi 获取 pptx 幻灯片注释文本?

java - 将空格的下一个字符设为大写

postgresql - PostgreSQL : 'now' keeps returning same old value 问题