public enum Dimension implements Serializable, IntegerValuedEnum {
LARGE(234, 60, 0), SMALL(125, 125, 1);
private final int width;
private final int height;
private final int code;
private Dimension(int width, int height, int code) {
this.width = width;
this.height = height;
this.code = code;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
@Override
public int getCode() {
return code;
}
public String getDisplay() {
return "" + this.width + "*" + this.height;
}
}
public class IntegerValuedEnumType<T extends Enum & IntegerValuedEnum> implements
EnhancedUserType, ParameterizedType {
/**
* Enum class for this particular user type.
*/
private Class<T> enumClass;
/**
* Value to use if null.
*/
private Integer defaultValue;
public IntegerValuedEnumType() { }
public void setParameterValues(Properties parameters) {
String enumClassName = parameters.getProperty("enum");
try {
enumClass = (Class<T>) Class.forName(enumClassName).asSubclass(Enum.class)
.asSubclass(IntegerValuedEnum.class);
} catch (ClassNotFoundException e) {
throw new HibernateException("Enum class not found", e);
}
String defaultValueStr = parameters.getProperty("defaultValue");
if (defaultValueStr != null && !defaultValueStr.isEmpty()) {
try {
setDefaultValue(Integer.parseInt(defaultValueStr));
} catch (NumberFormatException e) {
throw new HibernateException("Invalid default value", e);
}
}
}
public Integer getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(Integer defaultValue) {
this.defaultValue = defaultValue;
}
/**
* The class returned by <tt>nullSafeGet()</tt>.
*
* @return Class
*/
public Class returnedClass() {
return enumClass;
}
public int[] sqlTypes() {
return new int[] { Types.TINYINT };
}
public boolean isMutable() {
return false;
}
/**
* Retrieve an instance of the mapped class from a JDBC resultset.
* Implementors should handle possibility of null values.
*
* @param rs a JDBC result set
* @param names the column names
* @param owner the containing entity
* @return Object
* @throws HibernateException
* @throws SQLException
*/
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws SQLException {
Integer value = rs.getInt(names[0]);
if (value == null) {
value = getDefaultValue();
if (value == null) { // no default value
return null;
}
}
String name = IntegerValuedEnumReflect.getNameFromValue(enumClass, value);
if (rs.wasNull() || name == null || name.isEmpty()) {
return null;
} else {
return Enum.valueOf(enumClass, name);
}
}
/**
* Write an instance of the mapped class to a prepared statement.
* Implementors should handle possibility of null values. A multi-column
* type should be written to parameters starting from <tt>index</tt>.
*
* @param st a JDBC prepared statement
* @param value the object to write
* @param index statement parameter index
* @throws HibernateException
* @throws SQLException
*/
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws SQLException {
if (value == null) {
st.setNull(index, Types.TINYINT);
} else {
st.setInt(index, ((T) value).getCode());
}
}
public Object assemble(Serializable cached, Object owner) {
return cached;
}
public Serializable disassemble(Object value) {
return (Enum) value;
}
public Object deepCopy(Object value) {
return value;
}
public boolean equals(Object x, Object y) {
return x == y;
}
public int hashCode(Object x) {
return x.hashCode();
}
public Object replace(Object original, Object target, Object owner) {
return original;
}
public String objectToSQLString(Object value) {
return '\'' + String.valueOf(((T) value).getCode()) + '\'';
}
public String toXMLString(Object value) {
return String.valueOf(((T) value).getCode());
}
public Object fromXMLString(String xmlValue) {
Integer value = Integer.parseInt(xmlValue);
String name = IntegerValuedEnumReflect.getNameFromValue(enumClass, value);
if (name == null || name.isEmpty()) {
return null;
} else {
return Enum.valueOf(enumClass, name);
}
}
}
public final class IntegerValuedEnumReflect {
/**
* Don't let anyone instantiate this class.
*
* @throws UnsupportedOperationException
* Always.
*/
private IntegerValuedEnumReflect() {
throw new UnsupportedOperationException("This class must not be instanciated.");
}
/**
* All Enum constants (instances) declared in the specified class.
*
* @param enumClass Class to reflect
* @return Array of all declared EnumConstants (instances).
*/
private static <T extends Enum> T[] getValues(Class<T> enumClass) {
return enumClass.getEnumConstants();
}
/**
* All possible string values of the string valued enum.
*
* @param enumClass Class to reflect.
* @return Available integer values.
*/
public static <T extends Enum & IntegerValuedEnum> int[] getStringValues(
Class<T> enumClass) {
T[] values = getValues(enumClass);
int[] result = new int[values.length];
for (int i = 0; i < values.length; i++) {
result[i] = values[i].getCode();
}
return result;
}
/**
* Name of the enum instance which hold the respecified string value. If
* value has duplicate enum instances than returns the first occurrence.
*
* @param enumClass Class to inspect.
* @param value The int value.
* @return name of the enum instance.
*/
public static <T extends Enum & IntegerValuedEnum> String getNameFromValue(
Class<T> enumClass, int value) {
T[] values = getValues(enumClass);
for (int i = 0; i < values.length; i++) {
if (values[i].getCode() == value) {
return values[i].name();
}
}
return null;
}
}
public class IntegerValuedEnumSetType<T extends Enum<T> & IntegerValuedEnum> implements
EnhancedUserType, ParameterizedType {
/**
* Enum class for this particular user type.
*/
private Class<T> enumClass;
public IntegerValuedEnumSetType() { }
public void setParameterValues(Properties parameters) {
String enumClassName = parameters.getProperty("enum");
try {
enumClass = (Class<T>) Class.forName(enumClassName).asSubclass(Enum.class)
.asSubclass(IntegerValuedEnum.class);
} catch (ClassNotFoundException e) {
throw new HibernateException("Enum class not found", e);
}
}
/**
* The class returned by <tt>nullSafeGet()</tt>.
*
* @return Class
*/
public Class returnedClass() {
return enumClass;
}
public int[] sqlTypes() {
return new int[] { Types.TINYINT };
}
public boolean isMutable() {
return false;
}
/**
* Retrieve an instance of the mapped class from a JDBC resultset.
* Implementors should handle possibility of null values.
*
* @param rs a JDBC result set
* @param names the column names
* @param owner the containing entity
* @return Object
* @throws HibernateException
* @throws SQLException
*/
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws SQLException {
Integer value = rs.getInt(names[0]);
if (value == null) {
return null;
}
return decode(value);
}
/**
* Write an instance of the mapped class to a prepared statement.
* Implementors should handle possibility of null values. A multi-column
* type should be written to parameters starting from <tt>index</tt>.
*
* @param st a JDBC prepared statement
* @param value the object to write
* @param index statement parameter index
* @throws HibernateException
* @throws SQLException
*/
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws SQLException {
if (value == null) {
st.setNull(index, Types.TINYINT);
} else {
st.setInt(index, encode((EnumSet<T>)value));
}
}
public Object assemble(Serializable cached, Object owner) {
return cached;
}
public Serializable disassemble(Object value) {
return (Enum) value;
}
public Object deepCopy(Object value) {
return value;
}
public boolean equals(Object x, Object y) {
return x == y;
}
public int hashCode(Object x) {
return x.hashCode();
}
public Object replace(Object original, Object target, Object owner) {
return original;
}
public String objectToSQLString(Object value) {
return '\'' + String.valueOf(encode((EnumSet<T>)value)) + '\'';
}
public String toXMLString(Object value) {
return String.valueOf(encode((EnumSet<T>)value));
}
public Object fromXMLString(String xmlValue) {
try {
Integer value = Integer.parseInt(xmlValue);
return decode(value);
} catch (NumberFormatException e) {
return EnumSet.noneOf(enumClass);
}
}
/*
* Encode the EnumSet into an integer based on bit on/off
*/
private int encode(EnumSet<T> set) {
int ret = 0;
for (T val : set) {
ret |= 1 << val.getCode();
}
return ret;
}
/*
* Decode the integer back to a EnumSet based on bit on/off
*/
private EnumSet<T> decode(int code) {
Map<Integer, T> codeMap = new HashMap<Integer, T>();
for (T val : EnumSet.allOf(enumClass)) {
codeMap.put(val.getCode(), val);
}
EnumSet<T> result = EnumSet.noneOf(enumClass);
while (code != 0) {
int ordinal = Integer.numberOfTrailingZeros(code);
code ^= Integer.lowestOneBit(code);
result.add(codeMap.get(ordinal));
}
return result;
}
}
public interface IntegerValuedEnum {
/**
* Current int value stored in the enum.
* @return int value.
*/
int getCode();
}
maping.xml
<property name="dimension" column="DIMENSION">
<type name="com.xxx.bbb.hibernate.IntegerValuedEnumType">
<param name="enum">com.xxx.bbb.beans.Dimension</param>
</type>
</property>
存到数据库只是 0 1 2
转换器
public class DimensionConverter extends StrutsTypeConverter {
@Override
public Object convertFromString(Map arg0, String[] values, Class clazz) {
if (values != null && values.length > 0 && values[0] != null
&& !values[0].isEmpty()) {
String value = values[0];
if (value.equals("0")) {
return Dimension.LARGE;
} else if (value.equals("1")) {
return Dimension.SMALL;
}
}
return null;
}
@Override
public String convertToString(Map arg0, Object o) {
System.out.println(o.toString());
Dimension dimension = (Dimension) o;
return String.valueOf(dimension.getCode());
}
}
js
$("#dimensionSelect").val(${request.dimension.code});
<s:select id="dimensionSelect" name="dimension" list="#{@beans.Dimension@LARGE.code:@beans.Dimension@LARGE.display, @beans.Dimension@SMALL.code:@beans.Dimension@SMALL.display}" tabindex="4"/>