Hibernate fournit une annotation @Enumerated
qui prend en charge deux types de mappage Enum
en utilisant ORDINAL
ou STRING
. Lorsque nous mappons en utilisant EnumType.STRING
, il prend le "nom" de la variable Enum
et non la représentation toString()
de la énumération. Ceci est un problème dans les scénarios où la colonne de base de données est composée d'un seul caractère. Par exemple, j'ai l'énumération suivante:
public enum Status{
OPEN{
@Override
public String toString(){
return "O";}
},
WAITLIST{
@Override
public String toString(){
return "W";}
},
COMPLETE{
@Override
public String toString(){
return "C";}
}
}
Lorsque je persiste dans l'énumération Status.OPEN
en utilisant @Enumerated(EnumType.STRING)
, la valeur que Hibernate essaie de stocker dans la base de données est OPEN. Cependant, ma colonne de base de données ne contient qu'un seul caractère et génère donc une exception.
Une façon de résoudre ce problème consiste à modifier le type Enum afin qu'il contienne des caractères uniques (tels que STATUS.O
, STATUS.W
au lieu de STATUS.OPEN
, STATUS.WAITLIST
). Cependant, cela réduit la lisibilité. Avez-vous des suggestions pour préserver la lisibilité et mapper Enum sur une colonne à caractère unique?
Merci.
Vérifiez ces deux articles - http://community.jboss.org/wiki/Java5EnumUserType et http://community.jboss.org/wiki/UserTypeforpersistingaTypesafeEnumerationwithaVARCHARcolumn
Ils résolvent le problème par un UserType personnalisé.
Le meilleur moyen de personnaliser le mappage pour les enums est d'utiliser AttributeConverter
i.e:
@Entity
public class Person {
...
@Basic
@Convert( converter=GenderConverter.class )
public Gender gender;
}
public enum Gender {
MALE( 'M' ),
FEMALE( 'F' );
private final char code;
private Gender(char code) {
this.code = code;
}
public char getCode() {
return code;
}
public static Gender fromCode(char code) {
if ( code == 'M' || code == 'm' ) {
return MALE;
}
if ( code == 'F' || code == 'f' ) {
return FEMALE;
}
throw ...
}
}
@Converter
public class GenderConverter
implements AttributeConverter<Gender, Character> {
public Character convertToDatabaseColumn(Gender value) {
if ( value == null ) {
return null;
}
return value.getCode();
}
public Gender convertToEntityAttribute(Character value) {
if ( value == null ) {
return null;
}
return Gender.fromCode( value );
}
}
Vous pouvez le trouver dans la documentation d'Hibernate: http://docs.jboss.org/hibernate/orm/5.0/mappingGuide/en-US/html_single/#d5e678
Voici un exemple qui utilise des annotations.
http://www.gabiaxel.com/2011/01/better-enum-mapping-with-hibernate.html
Il est toujours basé sur un type d'utilisateur personnalisé. Quatre ans et demi plus tard et je ne connais toujours pas de meilleure façon de le faire.
En règle générale, je conserve mes valeurs enum sous la forme char/int, un ID simple, puis j'utilise une méthode transitoire qui recherche l'énum approprié par la valeur de l'ID simple, par exemple.
@Transient
public MyEnum getMyEnum() {
return MyEnum.findById(simpleId); //
}
et...
public enum MyEnum {
FOO('F'),
BAR('B');
private char id;
private static Map<Character, MyEnum> myEnumById = new HashMap<Character, MyEnum>();
static {
for (MyEnum myEnum : values()) {
myEnumById.put(myEnum.getId(), myEnum);
}
}
private MyEnum(char id) {
this.id = id;
}
public static MyEnum findById(char id) {
return myEnumById.get(id);
}
public char getId() {
return id;
}
}