【问题标题】:Is it possible to write a data type Converter to handle postgres JSON columns?是否可以编写一个数据类型转换器来处理 postgres JSON 列?
【发布时间】:2023-04-07 13:46:02
【问题描述】:

最好在 Java 方面使用 Jackson。我已经尝试了明显的解决方案:

public class JsonObjectConverter implements Converter<Object, ObjectNode> {

    private final ObjectMapper mapper = new ObjectMapper();

    @Override public ObjectNode from(Object dbo) {
        try {
            return dbo != null ? mapper.readValue((String) dbo, ObjectNode.class) : null;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override public Object to(ObjectNode uo) {
        try {
            return uo != null ? mapper.writeValueAsString(uo) : null;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

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

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

但如果我尝试使用它,我会收到如下错误:

org.jooq.exception.DataAccessException: SQL [insert into "public"."my_table" ("id", "stuff") values (?, ?)]; ERROR: column "stuff" is of type json but expression is of type character varying
  Hint: You will need to rewrite or cast the expression.

但是由于 jOOQs 强制类型安全(这很好,顺便说一句),我不能只添加一个 .cast(String.class) 就完成了。那么,我需要在转换器中做其他事情,还是应该以不同的方式调用代码?我目前正在这样做:

Long id = ...
ObjectNode stuff = ...
create.insertInto(MY_TABLE)
    .set(MY_TABLE.ID, id)
    .set(MY_TABLE.STUFF, stuff)
    .execute();

并且在我的代码的其他地方使用可更新记录。

【问题讨论】:

    标签: java sql postgresql jooq


    【解决方案1】:

    是的,但您需要使用 Postgres 特定的 API。在上面的代码中,您需要将 from/to 方法替换为以下内容:

    @Override
    public ObjectNode from(Object databaseObject) {
        if (databaseObject == null) { return null; }
        try {
            PGobject dbo = (PGobject) databaseObject;
            return mapper.readValue(dbo.getValue(), ObjectNode.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    @Override
    public Object to(ObjectNode userObject) {
        if (userObject == null) { return null; }
        try {
            PGobject dbo = new PGobject();
            dbo.setType("json");
            dbo.setValue(mapper.writeValueAsString(userObject));
            return dbo;
        } catch (JsonProcessingException|SQLException e) {
            throw new RuntimeException(e);
        }
    }
    

    【讨论】:

      【解决方案2】:

      仅使用Converter,您可能无法获得 100% 正确的 JSON 数据类型。理想情况下,您应该使用 jOOQ 3.5 org.jooq.Binding 实现,此处记录了该实现:

      可以将代码生成器配置为直接在您的数据库列上使用您的自定义Binding(代替Converters 或除了Converters)。然后Binding 将处理 JDBC 级别上的所有必要交互。

      【讨论】:

      • 是的,升级到 3.5 在我的待办事项清单上。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-24
      • 1970-01-01
      相关资源
      最近更新 更多