【问题标题】:How to map custom enumerated integer ordinals with hibernate?如何使用休眠映射自定义枚举整数序数?
【发布时间】:2012-07-16 11:11:32
【问题描述】:

我有一个名为 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:枚举类数据的未知序数值。状态:-1 在 org.hibernate.type.EnumType.nullSafeGet(EnumType.java:93) 在 org.hibernate.type.CustomType.nullSafeGet(CustomType.java:124) 在 org.hibernate.type.AbstractType.hydrate(AbstractType.java:106) 在

但我在枚举定义中已经有了 -1。

【问题讨论】:

    标签: java hibernate exception enumeration


    【解决方案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();
        }
    }
    

    【讨论】:

    • 我也是这样做的。但它给了我列“user_role_type”的类型是 users.user_role 但表达式的类型是 bytea
    【解决方案3】:

    我想建议以下解决方法。起初我很惊讶它有效,但它真的很简单: 对于枚举:

        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" />
    

    就是这样

    【讨论】:

      猜你喜欢
      • 2010-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 1970-01-01
      • 1970-01-01
      • 2017-05-28
      相关资源
      最近更新 更多