2009-01-06 17 views
82

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

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 me parece que la clase UserType ungly y que requieren demasiada burocracia sólo para almacenar un par de valores Idealmente, Hibernate debería admitir campos enum directamente y crearía una tabla adicional para almacenar los valores de enumeración.

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

Respuesta

110

usando Hibernate o anotaciones JPA:

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

UserType es sólo un estándar de Java 5 enum .

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

edición: es posible en un HBM, pero es un poco desordenado, echar un vistazo a este forum thread

+3

¿Podría @Enumerated (EnumType.ORDINAL) cuál mapa a int más eficiente? –

+4

problably es más eficiente, pero me gustaría poner dinero en no poder medir la diferencia en un sistema real. EnumType.ORDINAL es el valor predeterminado si solo hace @Enumerated. Creo que la mayoría de las personas (especialmente los DBA) tienden a preferir el nombre enum en el DB. –

+1

¿Cómo puedo cambiar la longitud de la columna para estas enumeraciones? Intenté agregar la anotación Columna pero eso no se cumple? –

15

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

se puede crear una nueva typedef para cada una de las enumeraciones y hacer referencia a los typedefs en la etiqueta de propiedad.

Ejemplo Mapping - inline <type> etiqueta

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

Ejemplo Mapping - usando <typedef>

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

    <class ...> 
    <property name='suit' type='suit'/> 
    </class> 
+0

Gracias. Ya sabía de esa solución. El problema es que requiere que todas las enumeraciones utilicen tipos internos de hibernación, lo que puede dar como resultado problemas si usa los DAO como DTO como en mi caso. Aquí se describe una mejor solución: http://www.hibernate.org/273.html –

+1

Tenga en cuenta que en las versiones más nuevas, el nombre del parámetro es 'enumClass' en lugar de' enumClassName'. –