提问人:edbras 提问时间:11/11/2023 更新时间:11/11/2023 访问量:34
通过 Spring 属性配置可配置的 Hibernate 枚举转换器?
Configurable Hibernate enum Converter through Spring property?
问:
如何创建一个可配置的 Hibernate 转换器,将 Java 枚举值转换为数据库值。我想通过spring属性进行配置,以指示是否应将枚举值转换为DB String值或DB整数(枚举序号值)。 我希望它是可配置的,以便它向后兼容,即:未配置时,它被转换为整数值,并且通过 spring 属性,我可以将其更改为 db String 值。该转换器将成为我的几个项目使用的共享外部 Java 库的一部分。
我尝试了几件事,似乎比我想象的要难得多。
我想出的是有 2 个转换器,1 个用于整数,1 个用于字符串,并通过 MetadataBuilderContributor 将其添加到休眠状态。
转换器:
public class ServerLogTypeDbConverter implements AttributeConverter<ServerlogEntryType, String> {
@Override
public String convertToDatabaseColumn(ServerlogEntryType attribute) {
return attribute.name();
}
@Override
public ServerlogEntryType convertToEntityAttribute(String dbData) {
return ServerlogEntryType.valueOf(dbData);
}
}
public class ServerLogTypeDbConverter implements AttributeConverter<ServerlogEntryType, Integer> {
@Override
public Integer convertToDatabaseColumn(ServerlogEntryType attribute) {
return attribute.ordinal();
}
@Override
public ServerlogEntryType convertToEntityAttribute(Integer dbData) {
return ServerlogEntryType.values()[ordinal];
}
}
然后的挑战是注册其中一个 Hibernate 转换器,具体取决于 spring 属性,以便它们被拾取。通过 SO 中的几篇文章,我想出了以下内容:当 spring-boot 应用程序启动时,在创建任何 bean 之前获得通知,读取属性,然后添加一个 hibernate 属性,该属性将使用休眠 MetadataBuilderContributor 添加转换器,在代码片段下方:
public class MetadataBuilderContributerResolver implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
var environment = event.getEnvironment();
var testValue = environment.getProperty("bla.test");
Class<?> metadataBuilderContributorClazz = switch (testValue) {
case "string" -> AttributeConverterMetadataBuilderContributor.class;
default -> throw new IllegalArgumentException("Unsupported builder: " + testValue);
};
var className = metadataBuilderContributorClazz.getName();
var props = new Properties();
props.put("spring.jpa.properties.hibernate.metadata_builder_contributor", className);
environment.getPropertySources().addFirst(new PropertiesPropertySource(this.getClass().getName(), props));
}
}
和:
public class AttributeConverterMetadataBuilderContributor implements MetadataBuilderContributor {
@Override
public void contribute(MetadataBuilder metadataBuilder) {
metadataBuilder.applyAttributeConverter(ServerLogTypeDbConverter.class);
}
}
这可行,但有 2 个主要缺点:
- Spring 侦听器必须通过代码添加到 Spring Boot 应用程序中(注释由 Spring bean 读取,它们尚不存在)。这在将包含此转换器的外部库中是很困难的。
- 接口 MetadataBuilderContributor 已弃用。我读到我需要使用 FunctionContributor,但不知道如何......
请一些建议,因为我现在😬有点卡住了
答: 暂无答案
评论