Как сопоставить пользовательские нумерованные целочисленные порядковые номера с 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" />

это оно