Перечисления в Hibernate

82

Часто бывает полезно иметь поле в DAO, значение которого берется из перечисления Java. Типичным примером является вход в систему DAO, в котором обычно есть поле, характеризующее пользователя как «НОРМАЛЬНЫЙ» или «АДМИНИСТРАТОР». В Hibernate я бы использовал следующие 2 объекта для представления этих отношений (полу) типизированным способом:

class User {
    String username;
    String passwd;
    UserType type;
}

class UserType {
    private enum Type {ADMIN, NORMAL};
    private String type;

    //Setters/Getters for Hibernate
    public void setType(String type);
    public String getType();

    //Setters/Getters for user
    public void setUserType(UserType.Type t);
    public UserType.Type getUserType();

    public static UserType fromType(UserType.Type t);
}

Это работает, но я считаю класс UserType некрасивым и требующим слишком много бюрократии только для хранения пары значений. В идеале Hibernate должен поддерживать поля перечисления напрямую и создавать дополнительную таблицу для хранения значений перечисления.

Мой вопрос: есть ли способ напрямую сопоставить класс перечисления в Hibernate? Если нет, достаточно ли хорош мой шаблон для представления перечислений или я что-то упускаю? Какие еще шаблоны используют люди?

Георгиос Гусиос
источник

Ответы:

110

с использованием аннотаций hibernate или JPA:

class User {
   @Enumerated(EnumType.STRING)
   UserType type
}

UserType - это просто стандартное перечисление java 5.

Я не могу представить, что это ограничивается только аннотациями, но на самом деле я не знаю, как это сделать с файлами hbm. Я предполагаю, что это может сильно зависеть от версии, но я почти уверен, что требуется спящий режим 3.2+.

edit: это возможно в hbm, но немного беспорядочно, посмотрите эту ветку форума

Гарет Дэвис
источник
3
Может ли @Enumerated (EnumType.ORDINAL) более эффективное сопоставление с int?
Ли Чи Киам
4
вероятно, более эффективен, но я бы положил деньги на невозможность измерить разницу в реальной системе. EnumType.ORDINAL фактически используется по умолчанию, если вы просто используете @Enumerated. Я думаю, что большинство людей (особенно администраторов баз данных) предпочитают имя перечисления в БД.
Гарет Дэвис
1
Как я могу изменить длину столбца для этих перечислений? Я попытался добавить аннотацию столбца, но это не было выполнено?
Каннан Эканат
2
Вы должны задать это как еще один вопрос.
Гарет Дэвис
2
Используйте STRING вместо ORDINAL, так как это позволяет добавлять дополнительные элементы в Enum независимо от порядка.
Мэтью Даумен,
14

Из документации Hibernate: http://www.hibernate.org/272.html

Вы можете создать новый typedef для каждого из ваших перечислений и ссылаться на typedef в теге свойства.

Пример сопоставления - встроенный <type>тег

  <property name='suit'>
    <type name="EnumUserType">
      <param name="enumClassName">com.company.project.Suit</param>
    </type>
  </property>

Пример сопоставления - использование <typedef>

  <typedef name="suit" class='EnumUserType'>
      <param name="enumClassName">com.company.project.Suit</param>
  </typedef>

  <class ...>
    <property name='suit' type='suit'/>
  </class>
Крейг
источник
Благодарю. Я уже знал об этом решении. Проблема в том, что он требует, чтобы все ваши перечисления использовали внутренние типы спящего режима, что может привести к проблемам, если вы используете DAO как DTO, как в моем случае. Лучшее решение фактически описано здесь: hibernate.org/273.html
Георгиос Гусиос, 06
1
Обратите внимание, что в более новых версиях используется имя параметра enumClassвместо enumClassName.
Райан Рэнсфорд