当前位置: 首页 > 知识库问答 >
问题:

如何使用JOOQ以通用方式转换PostgreSQL中JSON/JSONB列的任何类型的Java对象?

狄阳秋
2023-03-14

我想问的是,如何编写一个通用解决方案,在PostgreSQL数据库列中插入和选择任何类型的Java对象。此外,我必须使用(注入)我的Jackson ObjectMapper,因为它是预配置的Spring bean。我试图用一个自定义的ConverterProvider来解决这个问题,它在选择端工作得很好,但在我插入时没有调用我的转换器提供程序。我错过什么了吗?

我查看了jOOQ文档和一些关于投标解决方案的堆栈溢出文章,但我不想确切地指定用户类型。因此,我无法注册绑定,因为我无法声明确切的用户类型。

我的目标是:我想消除对每个JSONJSONB字段的存储库类中Java对象字符串序列化的要求(以及将我的ObjectMapper注入每个存储库的要求)。我不想为每个JSONB字段编写这段代码行,jOOQ应该用我的JSONConverterProvider在幕后完成。

.set(myJSONBTableField, JSONB.jsonb(objectMapper.writeValueAsString(myJavaObjectToStore))

我想简单地说:

.set(myJSONBTableField, myJavaObjectToStore)

我想让jOOQ在我的自定义ObjectMapperbean的帮助下存储任何类型的Java对象,如果DB列类型是JSONJSONB。我的JSONBConverterProvider在读取阶段调用,但不是在写入阶段。JSONBConverterProvider也有一个用于vica转换的转换器,但jOOQ不使用它。

我的jOOQ配置的相关部分:

@Bean
public DefaultConfigurationCustomizer ziffitJooqCustomizer(JSONConverterProvider converterProvider) {
        return configuration -> configuration
            .set(converterProvider)
            .settings()...

我的定制转换器提供商:

@ConditionalOnClass(DSLContext.class)
@Component
public class JSONConverterProvider implements ConverterProvider {

    private final ConverterProvider delegate = new DefaultConverterProvider();
    private final ObjectMapper mapper;

    public JSONConverterProvider(ObjectMapper mapper) {
        this.mapper = mapper;
    }

    @Override
    public <T, U> Converter<T, U> provide(Class<T> dbClass, Class<U> entityClass) {
        if (dbClass == JSON.class) {
            return getJSONConverter(dbClass, entityClass);
        } else if (dbClass == JSONB.class) {
            return getJSONBConverter(dbClass, entityClass);
        } else {
            // Delegate all other type pairs to jOOQ's default
            return delegate.provide(dbClass, entityClass);
        }
    }

    private <T, U> Converter<T, U> getJSONConverter(Class<T> dbClass, Class<U> entityClass) {
        return Converter.ofNullable(dbClass, entityClass,
            t -> {
                try {
                    return mapper.readValue(((JSON) t).data(), entityClass);
                } catch (Exception e) {
                    throw new DataTypeException("JSON deserialization error", e);
                }
            },
            u -> {
                try {
                    return (T) JSON.valueOf(mapper.writeValueAsString(u));
                } catch (Exception e) {
                    throw new DataTypeException("JSON serialization error", e);
                }
            }
        );
    }

    private <T, U> Converter<T, U> getJSONBConverter(Class<T> dbClass, Class<U> entityClass) {
        return Converter.ofNullable(dbClass, entityClass,
            t -> {
                try {
                    return mapper.readValue(((JSONB) t).data(), entityClass);
                } catch (Exception e) {
                    throw new DataTypeException("JSONB deserialization error", e);
                }
            },
            u -> {
                try {
                    return (T) JSONB.valueOf(mapper.writeValueAsString(u));
                } catch (Exception e) {
                    throw new DataTypeException("JSONB serialization error", e);
                }
            }
        );
    }
}

我使用如下读取查询:

dslCtx
  .select(myJSONBTableField)
  .from(myTable)
  .where(...)
  .fetchOptionalInto(myClazz);

这很好,请调用我的JSONBConverterProvider。

但我的write查询没有。我想这样使用write查询:

dslCtx
  .insertInto(myTable)
  .set(myJSONBTableField, myJavaObjectToStore)
  .execute();

共有1个答案

谭玄天
2023-03-14

ConverterProvider(以及RecordMapperProvider和RecordUnmapperProvider)在每列/成员匹配的基础上覆盖所有基于反射的自动数据类型转换功能的行为,这主要影响记录::from和记录::into方法,以及其他类型上的相关方法。

请注意,如果在不传递类文字的情况下投影字段,则会得到一条记录1

相反,请附加一个转换器

使用这种方法,您仍然可以使用fetchOptionalInto(myClazz)调用,它只会实现从MyMarkerInterface到myClazz的不安全降级

 类似资料:
  • 问题内容: 我正在尝试以下查询: (+1.0仅用于强制转换浮动。我的实际查询要复杂得多,此查询只是问题的测试用例。) 我得到了错误: 如果我添加显式强制转换: 错误变为: 我知道大多数jsonb值不能转换为浮点数,但是在这种情况下,我知道纬度都是JSON编号。 是否有一个将jsonb值强制转换为浮点数(或为不可广播的返回NULL)的函数? 问题答案: 要从中获得价值,有两种操作。第一个将返回。第二

  • 我正试图从JSONB转换为Google GSON JSONElement。我使用的转换器来自:https://www.jooq.org/doc/3.11/manual/code-generation/custom-data-type-bindings/ TableImpl中的列:

  • 在我的Java项目中,我是usinq、JOOQ,我希望更新JSONB值。但我的建造失败了。 我写了一段代码: 我收到了下一条信息: 我犯错的地方?

  • 我所拥有的是Postgresql中的一个文本列,我想将其转换为JSONB列。 null 是否有一种方法可以将文本完全转换为jsonb,以便能够成功地从test中查询? 我不想在下面的查询中将文本转换为json,因为稍后我需要在'a'上创建索引。

  • 我有一个字符串(jsonData)通过Jackson对象映射器映射到json,如下所示,映射到JaxB。 我能够很好地映射到上面的字符串。然而,我在映射到jooq JSON对象时遇到了问题。我想我现在必须将jsonData转换为jooq JSON。 我该怎么做? 或者我必须创建某种包装? 由jooq配置的DTO