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
_など)。ただし、これにより読みやすさが低下します。読みやすさを維持し、列挙型を単一の文字列にマッピングするための提案はありますか?
ありがとう。
次の2つの記事を確認してください- http://community.jboss.org/wiki/Java5EnumUserType および http://community.jboss.org/wiki/UserTypeforpersistingaTypesafeEnumerationwithaVARCHARcolumn
彼らは、カスタムUserTypeによって問題を解決します。
列挙型のマッピングをカスタマイズするのに最適なのは、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
これは注釈を使用する例です。
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;
}
}