Hibernate @Enumerated mapping - PullRequest
       1

Hibernate @Enumerated mapping

24 голосов
/ 27 марта 2011

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";}
   }

}

Когда я сохраняю enum Status.OPEN, используя @Enumerated(EnumType.STRING), значение, которое Hibernate пытается сохранить в базе данных, - OPEN.Однако мой столбец базы данных состоит только из одного символа и, следовательно, он генерирует исключение.

Один из способов решения этой проблемы - изменить тип Enum для хранения отдельных символов (например, STATUS.O, STATUS.W вместоSTATUS.OPEN, STATUS.WAITLIST).Однако это снижает читабельность.Любые предложения по сохранению читабельности, а также отображение Enum в один символьный столбец?

Спасибо.

Ответы [ 4 ]

14 голосов
/ 14 ноября 2015

Лучше всего настроить отображение для перечислений, используя AttributeConverter т.е.:

@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

8 голосов
/ 28 марта 2011

Отметьте эти две статьи - http://community.jboss.org/wiki/Java5EnumUserType и http://community.jboss.org/wiki/UserTypeforpersistingaTypesafeEnumerationwithaVARCHARcolumn

Они решают проблему с помощью пользовательского типа.

0 голосов
/ 27 августа 2015

Вот пример, в котором используются аннотации.

http://www.gabiaxel.com/2011/01/better-enum-mapping-with-hibernate.html

Он по-прежнему основан на пользовательском типе пользователя.Четыре с половиной года спустя, и я до сих пор не знаю лучшего способа сделать это.

Как правило, я сохраняю значения enum в виде 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;
    }
}
0 голосов
/ 02 марта 2012
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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...