Say you have a class which needs to save some mapped items, using any Enum for the key. Using this mapping it generates e.g. varbinary
(SQL Server) with a hexadecimal value.
@Entity
public abstract class X {
@ElementCollection
private Map<Enum, Boolean> values;
}
This works but the main issue is readability. The data in the database isn't human readable. trying to use @MapKeyEnumerated(EnumType.STRING)
or with EnumType.Ordinal doesn't work since the Enum can be any type and that saves the MyEnum.SOME_VALUE
as "SOME_VALUE".
Is it possible to intercept the save/retrieve and save a fully qualified name (com.x.myenum.value) or something legible which could be used to restore the enum instead of a hexadecimal value?
To store a Map where key is an enum, and get something human readable in db you could try:
@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>();
... }
where QuestionnaireDefinitionTranslation is the entity or value that will be fecthed given the Language enum.
In this example the map value is type: 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;
...
}
The class Language is an ordinary enum:
public enum Language {
EN, ES, FI, FR;
}
The idea to make this work is:
1. First persist a the owner class:
QuestionnaireDefinition questionnaireDef = new QuestionnaireDefinition();
em.persist(questionnaireDef );
and then the aggregated class using your enum as key.
QuestionnaireDefinitionTranslation translation = new QuestionnaireDefinitionTranslation();
translation.set(questionnaireDef);
translation.setLanguage(Language.En);
translation.setText("hello");
em.persist(translation);
voilá that's all, you can fetch known by your enum
QuestionnaireDefinition qd = em.find(1,QuestionnaireDefinition.class);
qd.getTranslations().get(Language.EN);
Be aware with transactions, LazyException and that stuff.