Отображение перечисления Hibernate

Мне нужно сопоставить перечисления, которые не реализовали интерфейс заранее, с существующей базой данных, которая хранит перечисления в той же таблице, что и класс владельца, используя @Enumerated(EnumType.STRING).

class A {
    HasName name;
}

interface HasName {
    String getName();
}

enum X implements HasName {
    John, Mary;

    public String getName() { return this.name(); }
}

enum Y implements HasName {
    Tom, Ann;

    public String getName() { return this.name(); }
}

Как в этом случае обрабатывать отображение? Сохранение в базе данных не меняется, поскольку все перечисления, реализующие интерфейс, будут иметь разные значения, но я не уверен, как объекты должны быть извлечены из БД (нужен ли мне настраиваемый сопоставитель, который попытается создать экземпляр enum с использованием указанных классов перечисления? Поддерживает ли Hibernate эту функцию изначально?).


person dm3    schedule 20.10.2009    source источник


Ответы (2)


Можно создать собственный UserType (например, этот) и использовать его из своих сопоставлений

<property name="type" not-null="true">
  <type name="at.molindo.util.hibernate.EnumUserType">
    <param name="enumClass">
      com.example.MyEnum
    </param>
  </type>
</property>

РЕДАКТИРОВАТЬ: Hibernate поставляется с собственным EnumType (начиная с 3.2 в hibernate-annotations, с 3.6 в hibernate-core - на момент написания не знал, что он находится в hibernate-annotations, но см. Ответ Диего).

person sfussenegger    schedule 20.10.2009
comment
В моем случае я не знаю, каким будет класс перечисления. При создании экземпляра A Hibernate должен будет выбрать одно из перечислений {X, Y}. - person dm3; 20.10.2009
comment
Настроить пример реализации UserType под свои нужды не составит большого труда. Например, вместо сохранения только значения вы также можете сохранить класс (например, com.example.X.John или X.John, но тогда вам понадобится сопоставление X с com.example.X) - person sfussenegger; 20.10.2009
comment
Значит, мне нужен настраиваемый картограф (не видел вашу ссылку на pastebin). Спасибо за ответ. - person dm3; 20.10.2009

Hibernate предоставляет org.hibernate.type.EnumType для отображения перечислимых типов. Например,

package com.igalia.enumerates;

public enum Status {
   BUSY,
   AVAILABLE;
}

package com.igalia.entities;

class MyClass {
   private Status status;
}

Затем выполните сопоставление Hibernate следующим образом:

<class name="MyClass">
   <id name="id">
      <generator class="native"/>
   </id>

   <property name="status">
      <type name="org.hibernate.type.EnumType">
         <param name="enumClass">com.igalia.enumerates.Status</param>
      </type>
   </property>
</class>

И это все. Если вы предпочитаете использовать аннотации JPA вместо hbm.xml, используйте @Enumerated (EnumType.STRING). Проверьте это здесь:

Перечисления в спящем режиме

person Diego Pino    schedule 21.10.2009
comment
Как установить для этого значение по умолчанию? Я добавил следующий элемент в ‹property name = status›, но у меня это не сработало: ‹имя столбца = STATUS not-null = true default = com.igalia.enumerates.Status.BUSY /› - person Timo Ernst; 27.04.2011
comment
@valmar вы можете инициализировать status на уровне класса (или сделать это в его конструкторе). Например, «частный статус status = Status.BUSY;» - person Diego Pino; 16.05.2011