web-dev-qa-db-ja.com

Hibernate @Enumeratedマッピング

Hibernateは、EnumまたはORDINALを使用した2種類のSTRINGマッピングをサポートする_@Enumerated_アノテーションを提供します。 _EnumType.STRING_を使用してマップする場合、EnumのtoString()表現ではなく、Enumの「名前」を使用します。これは、データベース列が1文字のみで構成されるシナリオの問題です。たとえば、次の列挙型があります。

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

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

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

}
_

@Enumerated(EnumType.STRING)を使用して列挙型_Status.OPEN_を永続化すると、Hibernateがデータベースに格納しようとする値はOPENになります。ただし、私のデータベース列は1文字のみで構成されているため、例外がスローされます。

この問題を解決する1つの方法は、列挙型を変更して単一の文字を保持することです(_STATUS.O_、_STATUS.W_ではなく_STATUS.OPEN_、_STATUS.WAITLIST_など)。ただし、これにより読みやすさが低下します。読みやすさを維持し、列挙型を単一の文字列にマッピングするための提案はありますか?

ありがとう。

27
saravana_pc

次の2つの記事を確認してください- http://community.jboss.org/wiki/Java5EnumUserType および http://community.jboss.org/wiki/UserTypeforpersistingaTypesafeEnumerationwithaVARCHARcolumn

彼らは、カスタムUserTypeによって問題を解決します。

8
Bozho

列挙型のマッピングをカスタマイズするのに最適なのは、AttributeConverterを使用することです。つまり、

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

Hibernate docsで見つけることができます: http://docs.jboss.org/hibernate/orm/5.0/mappingGuide/en-US/html_single/#d5e678

14
Ondrej Bozek

これは注釈を使用する例です。

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

それでもカスタムUserTypeに基づいています。 4年半後、私はまだこれを行うためのより良い方法を知りません。

通常、列挙値をchar/int、いくつかの単純なIDとして永続化し、一時的なメソッドを使用して、単純なID値によって適切な列挙型を見つけます。

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

そして...

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