Enumeraciones en Hibernate

82

A menudo es útil tener un campo en un DAO cuyo valor provenga de una enumeración de Java. Un ejemplo típico es un DAO de inicio de sesión donde normalmente tiene un campo que caracteriza al usuario como "NORMAL" o "ADMIN". En Hibernate, usaría los siguientes 2 objetos para representar esta relación de una manera (semi) segura:

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

Esto funciona, pero la clase UserType me parece desagradable y requiere demasiada burocracia solo para almacenar un par de valores. Idealmente, Hibernate debería admitir campos de enumeración directamente y crearía una tabla adicional para almacenar los valores de enumeración.

Mi pregunta es: ¿Hay alguna forma de mapear directamente una clase de enumeración en Hibernate? Si no es así, ¿mi patrón para representar enumeraciones es lo suficientemente bueno o me falta algo? ¿Qué otros patrones usa la gente?

Georgios Gousios
fuente

Respuestas:

110

usando anotaciones de hibernación o JPA:

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

UserType es solo una enumeración estándar de Java 5.

No puedo imaginar que esto se limite solo a anotaciones, pero en realidad no sé cómo hacer esto con archivos hbm. Puede que sea muy dependiente de la versión, supongo, pero estoy bastante seguro de que se requiere hibernate 3.2+.

editar: es posible en un hbm, pero es un poco desordenado, eche un vistazo a este hilo del foro

Gareth Davis
fuente
3
¿Podría @Enumerated (EnumType.ORDINAL) qué mapa para int más eficiente?
Lee Chee Kiam
4
probablemente sea más eficiente, pero yo apostaría dinero por no poder medir la diferencia en un sistema real. EnumType.ORDINAL es en realidad el valor predeterminado si solo hace @Enumerated. Creo que la mayoría de las personas (especialmente los DBA) tienden a preferir el nombre de enumeración en la base de datos.
Gareth Davis
1
¿Cómo puedo cambiar la longitud de la columna para estas enumeraciones? Intenté agregar la anotación de la columna pero eso no se cumple.
Kannan Ekanath
2
Necesitas hacer eso como otra pregunta.
Gareth Davis
2
Utilice STRING en lugar de ORDINAL, ya que le permite agregar elementos adicionales a la enumeración independientemente del orden.
Matthew Daumen
14

De la documentación de Hibernate: http://www.hibernate.org/272.html

Puede crear una nueva typedef para cada una de sus enumeraciones y hacer referencia a las typedefs en la etiqueta de propiedad.

Ejemplo de asignación: <type>etiqueta en línea

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

Ejemplo de mapeo: uso <typedef>

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

  <class ...>
    <property name='suit' type='suit'/>
  </class>
Craig
fuente
Gracias. Ya estaba al tanto de esa solución. El problema es que requiere que todas sus enumeraciones usen tipos internos de hibernación, lo que puede generar problemas si está usando los DAO como DTO como en mi caso. En realidad, se describe una mejor solución aquí: hibernate.org/273.html
Georgios Gousios
1
Tenga en cuenta que en las versiones más recientes el nombre del parámetro es en enumClasslugar de enumClassName.
Ryan Ransford