Hibernate @Enumerated mapping
Solution 1
Check these two articles - http://community.jboss.org/wiki/Java5EnumUserType and http://community.jboss.org/wiki/UserTypeforpersistingaTypesafeEnumerationwithaVARCHARcolumn
They solve the problem by a custom UserType.
Solution 2
The best to customize mapping for enums is to use 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 );
}
}
You can find it in Hibernate docs: http://docs.jboss.org/hibernate/orm/5.0/mappingGuide/en-US/html_single/#d5e678
Solution 3
Here is an example which uses annotations.
http://www.gabiaxel.com/2011/01/better-enum-mapping-with-hibernate.html
It's still based off of a custom UserType. Four and a half years later and I'm still not aware of a better way to do this.
Typically, I persist my enum values as a char / int, some simple ID, then use a transient method that finds the appropriate enum by the simple ID value, e.g.
@Transient
public MyEnum getMyEnum() {
return MyEnum.findById(simpleId); //
}
and...
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;
}
}
saravana_pc
Updated on November 08, 2020Comments
-
saravana_pc over 3 years
Hibernate provides
@Enumerated
annotation which supports two types ofEnum
mapping either usingORDINAL
orSTRING
. When we map usingEnumType.STRING
, it takes the "name" of theEnum
and not thetoString()
representation of the Enum. This is a problem in scenarios where the database column consists of only one character. For example, I have the following Enum:public enum Status{ OPEN{ @Override public String toString(){ return "O";} }, WAITLIST{ @Override public String toString(){ return "W";} }, COMPLETE{ @Override public String toString(){ return "C";} } }
When I persist the enum
Status.OPEN
using@Enumerated(EnumType.STRING)
, the value that Hibernate tries to store in the database is OPEN. However, my database column consists of only one character and hence it throws an exception.One way to overcome this issue is to change the Enum type to hold single characters (like
STATUS.O
,STATUS.W
instead ofSTATUS.OPEN
,STATUS.WAITLIST
). However, this reduces readability. Any suggestions to preserve the readability as well as mapping the Enum to a single character column?Thanks.