次のようにStatusという名前の列挙型クラスがあります
public enum Status {
PENDING(0), SUCCESS(1), FAILED(-1);
private int st;
private Status(int st){
this.st = st;
}
}
そして他のクラスから私はこのステータス列挙型をマッピングしようとします
public void setStatus(Status status) {
this.status = status;
}
@Enumerated(EnumType.ORDINAL)
public Status getStatus() {
return status;
}
このコードを実行すると、
Java.lang.IllegalArgumentException:列挙型クラスデータの不明な順序値。ステータス:org.hibernate.type.EnumType.nullSafeGet(EnumType.Java:93)の-1 org.hibernate.type.CustomType.nullSafeGet(CustomType.Java: 124)org.hibernate.type.AbstractType.hydrate(AbstractType.Java:106)で
しかし、列挙型の定義にはすでに-1があります。
Hibernateがこれらの列挙型をマップする方法を定義する独自のUserType
を定義できます。
序数は列挙値のインデックスを定義するため、FAILED
は序数2になることに注意してください。そのプロパティを使用して列挙をマップするには、UserType
実装が必要です。
いくつかのリンク:
これは、int idの代わりに文字列ラベルを使用するソリューションですが、簡単に適応できます。
public class User {
@Id
private int id;
@Type(type = "com.example.hibernate.LabeledEnumType")
private Role role;
}
public enum Role implements LabeledEnum {
ADMIN("admin"), USER("user"), ANONYMOUS("anon");
private final String label;
Role(String label) {
this.label = label;
}
@Override
public String getLabel() {
return label;
}
}
public interface LabeledEnum {
String getLabel();
}
public final class LabeledEnumType implements DynamicParameterizedType, UserType {
private Class<? extends Enum> enumClass;
@Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return x == y;
}
@Override
public int hashCode(Object x) throws HibernateException {
return x == null ? 0 : x.hashCode();
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
String label = rs.getString(names[0]);
if (rs.wasNull()) {
return null;
}
for (Enum value : returnedClass().getEnumConstants()) {
if (value instanceof LabeledEnum) {
LabeledEnum labeledEnum = (LabeledEnum) value;
if (labeledEnum.getLabel().equals(label)) {
return value;
}
}
}
throw new IllegalStateException("Unknown " + returnedClass().getSimpleName() + " label");
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.VARCHAR);
} else {
st.setString(index, ((LabeledEnum) value).getLabel());
}
}
@Override
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return original;
}
@Override
public Class<? extends Enum> returnedClass() {
return enumClass;
}
@Override
public int[] sqlTypes() {
return new int[]{Types.VARCHAR};
}
@Override
public void setParameterValues(Properties parameters) {
ParameterType params = (ParameterType) parameters.get( PARAMETER_TYPE );
enumClass = params.getReturnedClass();
}
}
次の回避策を提案したいと思います。最初はそれが機能することに驚いていましたが、それは本当に簡単です:列挙型の場合:
public enum Status {
PENDING(0), SUCCESS(1), FAILED(-1);
private int status;
private Status(int status){
this.status = status;
}
public String getStatus() {
return status;
}
public static Status parse(int id) {
Status status = null; // Default
for (Status item : Status.values()) {
if (item.getStatus().equals(id)) {
Status = item;
break;
}
}
return Status;
}
}
クラス
class StatedObject{
@Column("status")
private int statusInt;
public Status getStatus() {
return Status.parse(statusInt);
}
public void setStatus(Status paymentStatus) {
this.statusInt = paymentStatus.getStatus();
}
public String getStatusInt() {
return statusInt;
}
public void setStatusInt(int statusInt) {
this.statusInt = statusInt;
}
}
hibernate xmlファイルでhibernateを使用している場合、次のようになります。
<property name="statusInt " column="status" type="Java.lang.Integer" />
それだ