How to map custom enumerated integer ordinals with hibernate?
I would like to suggest following workaround. At first I was supprised it worked but it is really simple: For 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
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;
}
}
if you are using hibernate in hibernate xml file it would be:
<property name="statusInt " column="status" type="java.lang.Integer" />
that is it
You could define your own UserType
which defines how Hibernate should map those enums.
Note that the ordinal defines the index of the enum value and thus FAILED
would have the ordinal 2. To map the enum using its properties your need a UserType
implementation.
Some links:
- https://community.jboss.org/wiki/UserTypeForPersistingAnEnumWithAVARCHARColumn
- http://javadata.blogspot.de/2011/07/hibernate-and-enum-handling.html (look at the "Paramterized Enumeration in Hibernate" section)
Here is a solution where a string label is used instead of an int id, however it is simple to adapt.
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();
}
}