通过 Spring 属性配置可配置的 Hibernate 枚举转换器?

Configurable Hibernate enum Converter through Spring property?

提问人:edbras 提问时间:11/11/2023 更新时间:11/11/2023 访问量:34

问:

如何创建一个可配置的 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,但不知道如何......

请一些建议,因为我现在😬有点卡住了

Java Spring spring-Boot 休眠 枚举

评论


答: 暂无答案