如何使用 JOOQ 在 PostgreSQL 中插入带有 JSON 列的可更新记录?
Posted
技术标签:
【中文标题】如何使用 JOOQ 在 PostgreSQL 中插入带有 JSON 列的可更新记录?【英文标题】:How to insert a updatable record with JSON column in PostgreSQL using JOOQ? 【发布时间】:2015-01-18 14:46:28 【问题描述】:我关注了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 3.5(刚刚发布)之前,PostgreSQL 的 JSON 类型很难与 jOOQ 集成。我们现在改变了这一点。 Some preliminary information can be seen here on this user group thread。我们将很快更新手册等,我将详细回答这个问题。可以肯定的是,您使用的是 Jackson,对吗? 是的,我正在使用 Jackson。 【参考方案1】:当前的 jOOQ 版本
jOOQ 原生支持 JSON
和 JSONB
数据类型,因此您无需执行任何特定操作。
历史答案
从 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
= 用户类型),而且您还可以定义这些类型的方式:
这里给出了一个示例 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;
您现在可以通过代码生成器配置注册上述绑定:
<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>
【讨论】:
谢谢卢卡斯!您的解决方案和 v3.5 来得正是时候! @Lukas,如果我们不知道目标类型,我们想将任何 JSON 对象绑定到我们碰巧拥有的任何结果类型对象怎么办?转换器的所有示例,类型绑定是特定的DB-Type => User-Type
而不是 DB-Type => ?
(所有 postgres 对象到我们现在想要的任何东西)
@JaysonMinard:很难说。恐怕我不完全理解你的问题。也许您可以在 Stack Overflow 或user group 上提出一个新问题并进行一些解释?那我很乐意回答。
@LukasEder 我没有使用自动生成的代码,我需要 GSON 我该怎么办?
@LukasEder 完成,***.com/questions/55595910/…以上是关于如何使用 JOOQ 在 PostgreSQL 中插入带有 JSON 列的可更新记录?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jOOQ 更新 PostgreSQL 上复合列的单个子字段?
如何在 jOOQ 中转换“to_json()”PostgreSQL 函数?
使用 jOOQ 在 PostgreSQL 中进行 UPSERT