gpt4 book ai didi

java - 强制对枚举使用 JPA AttributeConverter

转载 作者:搜寻专家 更新时间:2023-10-31 08:03:33 26 4
gpt4 key购买 nike

我们正试图找到一种使用 JPA 持久保存枚举的可靠方法。使用@Enumerated 的常用方法是不可取的,因为重构时很容易破坏映射。每个枚举都应该有一个单独的数据库值,可以不同于枚举名称/顺序,这样您就可以安全地更改枚举的名称或内部顺序(例如,序号值)而不会破坏任何东西。例如。 this blog post 有一个关于如何实现此目的的示例,但我们认为建议的解决方案会使代码过于困惑。我们希望通过使用 JPA 2.1 中引入的新 AttributeConverter 机制来实现类似的结果。我们有一个每个枚举都应该实现的接口(interface),它定义了一个方法来获取用于将枚举存储在数据库中的值。示例:

public interface PersistableEnum {
String getDatabaseValue();
}

...

public enum SomeEnum implements PersistableEnum {
FOO("foo"), BAR("bar");

private String databaseValue;

private SomeEnum(String databaseValue) {
this.databaseValue = databaseValue;
}

public void getDatabaseValue() {
return databaseValue;
}
}

我们还有一个基本转换器,它具有将枚举转换为字符串的逻辑,反之亦然,并为每个枚举类型单独的具体转换器类(AFAIK,一个完全通用的枚举转换器是不可能实现的,这也被注意到 in this SO answer ).然后,具体转换器只需调用进行转换的基类,如下所示:

public abstract class EnumConverter<E extends PersistableEnum> {

protected String toDatabaseValue(E value) {
// Do the conversion...
}

protected E toEntityAttribute(Class<E> enumClass, String value) {
// Do the conversion...
}
}

...

@Converter(autoApply = true)
public class SomeEnumConverter extends EnumConverter<SomeEnum>
implements AttributeConverter<SomeEnum, String> {

public String convertToDatabaseColumn(SomeEnum attribute) {
return toDatabaseValue(attribute);
}

public SomeEnum convertToEntityAttribute(String dbData) {
return toEntityAttribute(SomeEnum.class, dbData);
}
}

然而,尽管这种方法在技术意义上非常有效,但仍然存在一个非常讨厌的陷阱:每当有人创建一个新的枚举类,其值需要存储到数据库中时,该人还需要记住创建新的枚举类enum 实现 PersistableEnum 接口(interface)并为其编写一个转换器类。如果没有这个,枚举将毫无问题地持久化,但转换将默认使用 @Enumerated(EnumType.ORDINAL),这正是我们想要避免的。我们如何防止这种情况发生?有没有办法让 JPA(在我们的例子中是 Hibernate)不默认为任何映射,但是例如如果没有在字段上定义 @Enumerated 并且找不到该类型的转换器,则抛出异常?或者我们可以创建一个“捕获所有”转换器,为所有没有自己特定转换器类的枚举调用,并且总是从那里抛出异常吗?还是我们每次都只能接受并尝试记住额外的步骤?

最佳答案

您要确保所有Enums 都是PersistableEnum 的实例。

您需要设置一个默认实体监听器(一个实体监听器,其回调适用于持久性单元中的所有实体)。

Default Entity Listener 类中实现@PrePersist 方法并确保所有Enums 都是PersistableEnum 的实例。

关于java - 强制对枚举使用 JPA AttributeConverter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24141546/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com