2011-03-27 12 views
23

Hibernate proporciona la anotación @Enumerated que admite dos tipos de mapeo Enum utilizando ORDINAL o STRING. Cuando mapeamos usando EnumType.STRING, toma el "nombre" de la Enum y no la toString() representación de Enum. Este es un problema en escenarios donde la columna de la base de datos consta de un solo carácter. Por ejemplo, tengo la siguiente enumeración:Hibernate @Enumerated mapping

public enum Status{ 
    OPEN{ 
    @Override 
    public String toString(){ 
    return "O";} 
    }, 

    WAITLIST{ 
    @Override 
    public String toString(){ 
    return "W";} 
    }, 

    COMPLETE{ 
    @Override 
    public String toString(){ 
    return "C";} 
    } 

} 

Cuando persisto la enumeración Status.OPEN usando @Enumerated(EnumType.STRING), el valor que Hibernate intenta almacenar en la base de datos está abierta. Sin embargo, mi columna de base de datos consta de un solo carácter y, por lo tanto, arroja una excepción.

Una forma de superar este problema es cambiar el tipo de enumeración para contener caracteres individuales (como STATUS.O, en lugar de STATUS.WSTATUS.OPEN, STATUS.WAITLIST). Sin embargo, esto reduce la legibilidad. ¿Alguna sugerencia para preservar la legibilidad, así como mapear el Enum en una sola columna de caracteres?

Gracias.

Respuesta

8

comprobar estos dos artículos - http://community.jboss.org/wiki/Java5EnumUserType y http://community.jboss.org/wiki/UserTypeforpersistingaTypesafeEnumerationwithaVARCHARcolumn

Ellos resuelven el problema por un UserType personalizado.

+3

¿Alguien ha utilizado la solución del enlace anterior y ha podido hacer el mapeo enum? Estoy usando Hibernate 3.6.7 y no tengo el método TypeFactory.basic. ¿Algún indicio de cómo debo seguir adelante? – yousafsajjad

+0

El enlace a un artículo no es el formato correcto para una respuesta. – Arashsoft

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

-1, no resuelve el problema de mapeo JPA en absoluto. –

0

Aquí hay un ejemplo que utiliza anotaciones.

http://www.gabiaxel.com/2011/01/better-enum-mapping-with-hibernate.html

Todavía se basa fuera de un UserType personalizado. Cuatro años y medio después y todavía no estoy enterado de una mejor manera de hacer esto.

Normalmente, persisto mis valores de enum como un char/int, una identificación simple, luego uso un método transitorio que encuentra la enumeración adecuada por el valor de ID simple, p.

@Transient 
public MyEnum getMyEnum() { 
    return MyEnum.findById(simpleId); // 
} 

y ...

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

La mejor manera de personalizar el mapeo de las enumeraciones es utilizar AttributeConverter es decir:

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

Puede encontrarlo en Hibernate docs: http://docs.jboss.org/hibernate/orm/5.0/mappingGuide/en-US/html_single/#d5e678

+0

Método recomendado si está utilizando Hibernate 5.xy versiones posteriores. –

+0

¿No debería ser al revés - 'AttributeConverter '? JavaDoc dice que '@param X es el tipo de atributo de la entidad; @param Y es el tipo de columna de la base de datos'. – naXa

+0

Sí, tienes razón, lo corregiré en mi respuesta. –