在 Hibernate 中使用 Spring boot 配置的 Jackson Objectmapper

Jul*_*nen 12 java spring hibernate spring-boot hibernate-types

我想将 Hibernate 配置为使用 Spring 创建的 JacksonObjectmapper在 json 和实体之间进行映射。在我正在从事的项目中,我已经将 Jooq 配置为使用 Spring ObjectMapper,但我在如何配置 Hibernate 以使用它方面遇到了麻烦。最终的目标是 Jooq 和 Hibernate 都将使用相同的ObjectMapper是 Jooq 和 Hibernate 都使用相同的.

我查了弗拉德的这篇文章。不幸的是,本文中给出的所有提示不适用于我正在从事的项目。

这是我尝试过的示例配置

@Configuration
public class HibernateConfiguration implements HibernatePropertiesCustomizer {
    //Autowire Objectmapper created by Spring
    @Autowired
    ObjectMapper objectMapper;

    @Override
    public void customize(Map<String, Object> hibernateProperties) {
        ObjectMapperSupplier objectMapperSupplier = () -> objectMapper;
        // Below config doesn't work since Hibernate types creates it's own mapper
        hibernateProperties.put("hibernate.types.jackson.object.mapper", objectMapperSupplier);
}
Run Code Online (Sandbox Code Playgroud)

还尝试了相同的方法,将 Objectmapper 添加到 hibernate-types.properties 中。

#Used by Hibernate but cannot get reference of Spring managed ObjectMapper since this is class is called outside of Spring's context.
hibernate.types.jackson.object.mapper=path.to.ObjectMapperSupplier
Run Code Online (Sandbox Code Playgroud)

NullpointerException我使用了另一种方法,但在从 JSON 转换为类中的实体时失败JsonTypeDescriptor

@Configuration
public class HibernateConfiguration implements HibernatePropertiesCustomizer{

    @Autowired
    ObjectMapper objectMapper;

    @Override
    public void customize(Map<String, Object> hibernateProperties) {
        // Underlying implementation needs some JavaType or propertyClass, otherwise when converting 
        // from JSON we get a nullpointer.
        var jsonBinaryType = new JsonBinaryType(objectMapper);
        hibernateProperties.put("hibernate.type_contributors", (TypeContributorList) () -> 
        Collections.singletonList((typeContributions, serviceRegistry) -> 
                      typeContributions.contributeType(jsonBinaryType)));
}
Run Code Online (Sandbox Code Playgroud)

下面是实体超类的类型声明。

// This makes Hibernate types create it's own mapper.
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
@MappedSuperclass
public abstract class Entity{

}
Run Code Online (Sandbox Code Playgroud)

那么,是否有任何可能的解决方案可以将 Spring 管理的 ObjectMapper 连接到 Hibernate?

aku*_*ma8 11

对于那些使用 Spring Boot 3 和 Hibernate 6 的人,请查看Andy Wilkinson 提供的这个解决方案:

    @Bean
    public HibernatePropertiesCustomizer jsonFormatMapperCustomizer(ObjectMapper objectMapper) {
        return properties -> properties
                .put(AvailableSettings.JSON_FORMAT_MAPPER, new JacksonJsonFormatMapper(objectMapper));
    }
Run Code Online (Sandbox Code Playgroud)


小智 6

我终于明白了这一点,但这是一种创造性的解决方案......

TLDR:我有一个将 Spring 配置存储objectMapper在静态字段中的 bean。BeanFactoryPostProcessor 确保在 Hibernate(类型)尝试加载/获取 ObjectMapper 之前初始化该 bean。

休眠属性

hibernate.types.jackson.object.mapper=com.github.lion7.example.HibernateObjectMapperSupplier
Run Code Online (Sandbox Code Playgroud)

HibernateObjectMapperSupplier.kt

hibernate.types.jackson.object.mapper=com.github.lion7.example.HibernateObjectMapperSupplier
Run Code Online (Sandbox Code Playgroud)

与要点相同的代码:https://gist.github.com/lion7/c8006b69a309e38183deb69124b888b5