Как сопоставить пользовательские нумерованные целочисленные порядковые номера с hibernate?
У меня есть класс перечисления с именем 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: Неизвестное порядковое значение для данных класса enum.Status: -1 на org.hibernate.type.EnumType.nullSafeGet(EnumType.java:93) на org.hibernate.type.CustomType.nullSafeGet(CustomType.java:124) at org.hibernate.type.AbstractType.hydrate(AbstractType.java:106) при
но у меня уже есть -1 в определении перечисления.
Ответы
Ответ 1
Вы можете определить свой собственный UserType
, который определяет, как Hibernate должен отображать эти перечисления.
Обратите внимание, что порядковый номер определяет индекс значения перечисления и, следовательно, FAILED
будет иметь порядковый номер 2. Чтобы отобразить перечисление с использованием его свойств, вам понадобится реализация UserType
.
Некоторые ссылки:
Ответ 2
Вот решение, в котором вместо 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();
}
}
Ответ 3
Я хотел бы предложить следующий обходной путь. Сначала я был удивлен, что это работает, но это действительно просто: Для enum:
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 в hibernate xml файле, это будет:
<property name="statusInt " column="status" type="java.lang.Integer" />
это оно