JSP 中Hibernate實(shí)現(xiàn)映射枚舉類(lèi)型
問(wèn)題:
Java BO類(lèi)Gender是枚舉類(lèi)型,想在數(shù)據(jù)庫(kù)中存成字符串格式,如何編寫(xiě)hbm.xml?
public enum Gender{ UNKNOWN("Unknown"), MALE("Male"), FEMALE("Female"); private String key; private Gender(final String key) { this.key = key; } public getGender(String key) { for (Gender gender : Gender.values()) { if (key.euqals(gender.getKey())) return gender; } throw new NoSuchElementException(key); } } 使用UserType:
public class GenderUserType implements UserType { private static int[] typeList = { Types.VARCHAR}; /* * Return the SQL type codes for the columns mapped by this type. * The codes are defined on <tt>java.sql.Types</tt>. */ /**設(shè)置和Gender類(lèi)的sex屬性對(duì)應(yīng)的字段的SQL類(lèi)型 */ public int[] sqlTypes() { return typeList; } /*The class returned by <tt>nullSafeGet()</tt>.*/ /** 設(shè)置GenderUserType所映射的Java類(lèi):Gender類(lèi) */ public Class returnedClass() { return Gender.class; } /** 指明Gender類(lèi)是不可變類(lèi) */ public boolean isMutable() { return false; } /* * Return a deep copy of the persistent state, stopping at entities and at * collections. It is not necessary to copy immutable objects, or null * values, in which case it is safe to simply return the argument. */ /** 返回Gender對(duì)象的快照,由于Gender類(lèi)是不可變類(lèi), 因此直接將參數(shù)代表的Gender對(duì)象返回 */ public Object deepCopy(Object value) { return (Gender)value; } /** 比較一個(gè)Gender對(duì)象是否和它的快照相同 */ public boolean equals(Object x, Object y) { //由于內(nèi)存中只可能有兩個(gè)靜態(tài)常量Gender實(shí)例, //因此可以直接按內(nèi)存地址比較 return (x == y); } public int hashCode(Object x){ return x.hashCode(); } /* * Retrieve an instance of the mapped class from a JDBC resultset. Implementors * should handle possibility of null values. */ /** 從JDBC ResultSet中讀取key,然后返回相應(yīng)的Gender實(shí)例 */ public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException{ //從ResultSet中讀取key String sex = (String) Hibernate.STRING.nullSafeGet(rs, names[0]); if (sex == null) { return null; } //按照性別查找匹配的Gender實(shí)例 try { return Gender.getGender(sex); }catch (java.util.NoSuchElementException e) { throw new HibernateException("Bad Gender value: " + sex, e); } } /* * 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>. */ /** 把Gender對(duì)象的key屬性添加到JDBC PreparedStatement中 */ public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException{ String sex = null; if (value != null) sex = ((Gender)value).getKey(); Hibernate.String.nullSafeSet(st, sex, index); } /* * Reconstruct an object from the cacheable representation. At the very least this * method should perform a deep copy if the type is mutable. (optional operation) */ public Object assemble(Serializable cached, Object owner){ return cached; } /* * Transform the object into its cacheable representation. At the very least this * method should perform a deep copy if the type is mutable. That may not be enough * for some implementations, however; for example, associations must be cached as * identifier values. (optional operation) */ public Serializable disassemble(Object value) { return (Serializable)value; } /* * During merge, replace the existing (target) value in the entity we are merging to * with a new (original) value from the detached entity we are merging. For immutable * objects, or null values, it is safe to simply return the first parameter. For * mutable objects, it is safe to return a copy of the first parameter. For objects * with component values, it might make sense to recursively replace component values. */ public Object replace(Object original, Object target, Object owner){ return original; } } 然后再hbm.xml中定義映射關(guān)系:
<hibernate-mapping package="" default-lazy="true" default-cascade="save-update,merge,persist"> <typedef name="Gender" class="com.alpha.hibernate.GenderUserType"> <property name="gender" type="Gender"> <column name="GENDER" not-null="true"> </column> </property>
延伸:
為每個(gè)枚舉類(lèi)型定義一個(gè)UserType是比較麻煩的,可以定義一個(gè)抽象類(lèi)。
例如擴(kuò)展下例即可適用于所有保存為index的枚舉類(lèi)型
public abstract class OrdinalEnumUserType<E extends Enum<E>> implements UserType { protected Class<E> clazz; protected OrdinalEnumUserType(Class<E> clazz) { this.clazz = clazz; } private static final int[] SQL_TYPES = {Types.NUMERIC}; public int[] sqlTypes() { return SQL_TYPES; } public Class<?> returnedClass() { return clazz; } public E nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException { //Hibernate.STRING.nullSafeGet(rs, names[0]) int index = resultSet.getInt(names[0]); E result = null; if (!resultSet.wasNull()) { result = clazz.getEnumConstants()[index]; } return result; } public void nullSafeSet(PreparedStatement preparedStatement, Object value,int index) throws HibernateException, SQLException { if (null == value) { preparedStatement.setNull(index, Types.NUMERIC); } else { //Hibernate.String.nullSafeSet(st, sex, index); preparedStatement.setInt(index, ((E)value).ordinal()); } } public Object deepCopy(Object value) throws HibernateException{ return value; } public boolean isMutable() { return false; } public Object assemble(Serializable cached, Object owner) throws HibernateException { return cached; } public Serializable disassemble(Object value) throws HibernateException { return (Serializable)value; } public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } public int hashCode(Object x) throws HibernateException { return x.hashCode(); } public boolean equals(Object x, Object y) throws HibernateException { if (x == y) return true; if (null == x || null == y) return false; return x.equals(y); } } 感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的
新聞熱點(diǎn)
疑難解答
圖片精選