我遵循了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 原生支持 JSON
和 JSONB
数据类型,因此您无需执行任何特定操作。
历史答案
从 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/