假设你有一个类需要保存一些映射的项目,使用任何枚举作为键。使用此映射,它可以生成例如 具有十六进制值的varbinary
(SQL Server)。
@Entity
public abstract class X {
@ElementCollection
private Map<Enum, Boolean> values;
}
这有效,但主要问题是可读性。数据库中的数据不是人类可读的。尝试使用 @MapKeyEnumerated(EnumType.STRING)
或与 EnumType.Ordinal 一起使用不起作用,因为枚举可以是任何类型,并且将MyEnum.SOME_VALUE
保存为"SOME_VALUE"。
是否可以拦截保存/检索并保存完全限定的名称(com.x.myenum.value)或可用于恢复枚举而不是十六进制值的清晰名称?
要存储一个键是枚举的 Map,并在 db 中获取人类可读的内容,您可以尝试:
@Entity
public class QuestionnaireDefinition{
...
@OneToMany(mappedBy = "questionnaireDefinition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@MapKeyEnumerated(EnumType.STRING)
@MapKeyColumn(name = "language", insertable = false, updatable = false)
private final Map<Language, QuestionnaireDefinitionTranslation> translations = new HashMap<Language, QuestionnaireDefinitionTranslation>();
... }
其中,问卷定义翻译是给定语言枚举的实体或值。在此示例中,映射值的类型为:问卷定义翻译
@Entity
public class QuestionnaireDefinitionTranslation {
@Enumerated(EnumType.STRING)
@Column(nullable = false, insertable = true, updatable = true)
private Language language;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private QuestionnaireDefinition questionnaireDefinition;
private String text;
...
}
类语言是一个普通的枚举:
public enum Language {
EN, ES, FI, FR;
}
制作这项工作的想法是:1. 首先持久化一个所有者类:
QuestionnaireDefinition questionnaireDef = new QuestionnaireDefinition();
em.persist(questionnaireDef );
然后使用枚举作为键的聚合类。
QuestionnaireDefinitionTranslation translation = new QuestionnaireDefinitionTranslation();
translation.set(questionnaireDef);
translation.setLanguage(Language.En);
translation.setText("hello");
em.persist(translation);
瞧,仅此而已,您可以通过枚举获取已知的
内容QuestionnaireDefinition qd = em.find(1,QuestionnaireDefinition.class);
qd.getTranslations().get(Language.EN);
注意交易,LazyException之类的东西。