Ответ 1
Проверьте эти две статьи - http://community.jboss.org/wiki/Java5EnumUserType и http://community.jboss.org/wiki/UserTypeforpersistingaTypesafeEnumerationwithaVARCHARcolumn
Они решают проблему с помощью пользовательского UserType.
Hibernate предоставляет аннотацию @Enumerated
, которая поддерживает два типа отображения Enum
либо с использованием ORDINAL
, либо STRING
. Когда мы на карте используем EnumType.STRING
, оно принимает "имя" Enum
, а не toString()
представления Enum. Это проблема в сценариях, где столбец базы данных состоит только из одного символа. Например, у меня есть следующий 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";}
}
}
Когда я сохраняю перечисление Status.OPEN
с помощью @Enumerated(EnumType.STRING)
, значение, которое Hibernate пытается сохранить в базе данных, ОТКРЫТО. Однако мой столбец базы данных состоит только из одного символа и, следовательно, генерирует исключение.
Один из способов преодоления этой проблемы - изменить тип Enum для хранения отдельных символов (например, STATUS.O
, STATUS.W
вместо Status.OPEN
, STATUS.WAITLIST
). Однако это снижает читаемость. Любые предложения по сохранению читаемости, а также отображение Enum в столбец с одним символом?
Спасибо.
Проверьте эти две статьи - http://community.jboss.org/wiki/Java5EnumUserType и http://community.jboss.org/wiki/UserTypeforpersistingaTypesafeEnumerationwithaVARCHARcolumn
Они решают проблему с помощью пользовательского UserType.
Лучше всего настроить отображение для перечислений - использовать 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 );
}
}
Вы можете найти его в документах Hibernate: http://docs.jboss.org/hibernate/orm/5.0/mappingGuide/en-US/html_single/#d5e678
Вот пример, который использует аннотации.
http://www.gabiaxel.com/2011/01/better-enum-mapping-with-hibernate.html
Он по-прежнему основан на пользовательском типе UserType. Четыре с половиной года спустя, и я до сих пор не знаю, как лучше это сделать.
Как правило, я сохраняю свои значения перечисления как char/int, некоторый простой идентификатор, а затем использует переходный метод, который находит соответствующее перечисление с помощью простого значения идентификатора, например.
@Transient
public MyEnum getMyEnum() {
return MyEnum.findById(simpleId); //
}
и...
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;
}
}
public enum Status
{
OPEN("O"),
WAITLIST("W"),
COMPLETE("C")
private String description;
private Status(String description)
{
this.description = description;
}
public String getDescription()
{
return description;
}
}
and then when you read it:
Status.OPEN.getDescription()