Подтвердить что ты не робот

Hibernate @Индивидуальное сопоставление

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 в столбец с одним символом?

Спасибо.

4b9b3361

Ответ 2

Лучше всего настроить отображение для перечислений - использовать 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

Ответ 3

Вот пример, который использует аннотации.

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

Ответ 4

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()