如何解决在 Hibernate 中使用 Spring boot 配置的 Jackson Objectmapper
我想将 Hibernate 配置为使用 Spring 创建的 Jackson 的 Objectmapper
在 json 和实体之间进行映射。在我正在处理的项目中,我已经将 Jooq 配置为使用 Spring 的 ObjectMapper
,但是我在如何配置 Hibernate 以使用它时遇到了麻烦。 目标最终是让 Jooq 和 Hibernate 使用相同的 ObjectMapper
。
我检查了弗拉德的这个article。不幸的是,文章中给出的所有技巧都不适用于我正在从事的项目。
这是我尝试过的示例配置
@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);
}
也尝试了相同的方法,将 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
我使用的另一种方法,但在从 JSON 转换为 NullpointerException
类中的实体时失败并显示 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)));
}
以下是实体超类的类型声明。
// This makes Hibernate types create it's own mapper.
@TypeDef(name = "jsonb",typeClass = JsonBinaryType.class)
@MappedSuperclass
public abstract class Entity{
}
那么,是否有任何可能的解决方案可以将 Spring 管理的 ObjectMapper 连接到 Hibernate?
解决方法
我终于想通了,但这是一个创造性的解决方案......
TLDR:我有一个 bean,它将 Spring 配置的 objectMapper
存储在静态字段中。 BeanFactoryPostProcessor 确保在 Hibernate(类型)尝试加载/获取 ObjectMapper 之前初始化此 bean。
hibernate.properties
hibernate.types.jackson.object.mapper=com.github.lion7.example.HibernateObjectMapperSupplier
HibernateObjectMapperSupplier.kt
package com.github.lion7.example
import com.fasterxml.jackson.databind.ObjectMapper
import com.vladmihalcea.hibernate.type.util.ObjectMapperSupplier
import org.springframework.beans.factory.config.BeanFactoryPostProcessor
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.stereotype.Component
class HibernateObjectMapperSupplier : ObjectMapperSupplier {
override fun get(): ObjectMapper =
ObjectMapperHolder.objectMapper
}
@Component
class ObjectMapperHolder(objectMapper: ObjectMapper) {
companion object {
lateinit var objectMapper: ObjectMapper
}
init {
Companion.objectMapper = objectMapper
}
}
@Component
class ObjectMapperDependencyFixer : BeanFactoryPostProcessor {
override fun postProcessBeanFactory(beanFactory: ConfigurableListableBeanFactory) {
val beanDefinition = beanFactory.getBeanDefinition("entityManagerFactory")
val oldDependsOn = beanDefinition.dependsOn ?: emptyArray()
val newDependsOn = oldDependsOn + "objectMapperHolder"
beanDefinition.setDependsOn(*newDependsOn)
}
}
与要点相同的代码:https://gist.github.com/lion7/c8006b69a309e38183deb69124b888b5
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。