扩展Hibernate对Enum的支持
最近项目中,用实体与枚举关联,一直觉得这种方式比较不错,有幸在项目中用到并扩展。
1.持久化枚举接口
package org.lop.modules.orm.hibernate.type; import java.util.Map; /** * 自定义Hibernate持久化枚举接口.<br> * 实体需要用枚举关联, 枚举必须实现该接口. * * <pre> * 实体映射eg. * <code>@Column( name = "COLUMN_NAME" )</code> * <code>@Type( type = CustomEnumType.ENUM_TYPE,</code> * <code> parameters = { @Parameter( name = "enumClass", value = "xxx.xxx.WorkDayType" ) } )</code> * </pre> * * @author 丁当 * @date 2012-11-02 */ public interface PersistentEnum<E extends Enum<?>, T> { T getValue(); String getDisplayName(); E getEnum( T value ); Map<T, E> getAllValueMap(); }
2.扩展Hibernate对Enumd支持
package org.lop.modules.orm.hibernate.type; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.apache.commons.beanutils.MethodUtils; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.compare.EqualsHelper; import org.hibernate.type.EnumType; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; import org.jboss.logging.Logger; import com.ylink.ylpay.common.project.mp.constant.WorkDayType; /** * 自定义Hibernate对Enum的持久化.<br> * 支持Enum的value为Number或String, 但Enum必须实现PersistentEnum接口. * * @author 丁当 * @date 2012-11-02 */ @SuppressWarnings( "serial" ) public class CustomEnumType implements UserType, ParameterizedType, Serializable { private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, CustomEnumType.class.getName() ); public static final String ENUM_TYPE = "org.lop.modules.orm.hibernate.type.CustomEnumType"; private static final String GETENUM_METHOD_NAME = "getEnum"; private static final String GETVALUE_METHOD_NAME = "getValue"; private Class<Enum<?>> enumClass; private Object enumObject; private int sqlType = Types.VARCHAR; @Override @SuppressWarnings( "unchecked" ) public void setParameterValues( Properties parameters ) { if ( null != parameters ) { String enumClassName = parameters.getProperty( EnumType.ENUM ); try { enumClass = ReflectHelper.classForName( enumClassName, this.getClass() ).asSubclass( Enum.class ); enumObject = enumClass.getEnumConstants()[ 0 ]; } catch ( ClassNotFoundException exception ) { throw new HibernateException( "Enum class not found", exception ); } } } @Override public Object nullSafeGet( ResultSet rs, String[] names, SessionImplementor session, Object owner ) throws HibernateException, SQLException { Object param = rs.getObject( names[ 0 ] ); Object returnVal = null; if ( rs.wasNull() ) { if ( LOG.isTraceEnabled() ) LOG.tracev( "Returning null as column {0}", names[ 0 ] ); return null; } try { /* 转换参数类型. */ if ( param instanceof Number ) { returnVal = MethodUtils.invokeMethod( enumObject, GETENUM_METHOD_NAME, ( ( Number ) param ).intValue() ); } else { returnVal = MethodUtils.invokeMethod( enumObject, GETENUM_METHOD_NAME, param ); } } catch ( NoSuchMethodException e ) { e.printStackTrace(); } catch ( IllegalAccessException e ) { throw new IllegalArgumentException( "Unknown name value for enum " + enumClass + ": " + param, e ); } catch ( InvocationTargetException e ) { e.printStackTrace(); } return returnVal; } @Override public void nullSafeSet( PreparedStatement st, Object value, int index, SessionImplementor session ) throws HibernateException, SQLException { if ( value == null ) { if ( LOG.isTraceEnabled() ) LOG.tracev( "Binding null to parameter: {0}", index ); st.setNull( index, sqlType ); } Object enumVal = null; try { enumVal = MethodUtils.invokeMethod( value, GETVALUE_METHOD_NAME, null ); if ( enumVal instanceof Number ) { sqlType = Types.INTEGER; } st.setObject( index, enumVal, sqlType ); } catch ( NoSuchMethodException e ) { e.printStackTrace(); } catch ( IllegalAccessException e ) { e.printStackTrace(); } catch ( InvocationTargetException e ) { e.printStackTrace(); } } @Override public int[] sqlTypes() { return new int[] { sqlType }; } @Override @SuppressWarnings( "rawtypes" ) public Class returnedClass() { return enumClass; } @Override public boolean equals( Object x, Object y ) throws HibernateException { return EqualsHelper.equals( x, y ); } @Override public int hashCode( Object x ) throws HibernateException { return x.hashCode(); } @Override public Object deepCopy( Object value ) throws HibernateException { return value; } @Override public boolean isMutable() { return false; } @Override public Serializable disassemble( Object value ) throws HibernateException { return ( Serializable ) value; } @Override public Object assemble( Serializable cached, Object owner ) throws HibernateException { return cached; } @Override public Object replace( Object original, Object target, Object owner ) throws HibernateException { return original; } }
3.eg.Enum
package org.lop.xxx.xxx; import java.util.HashMap; import java.util.Map; import org.lop.modules.orm.hibernate.type.PersistentEnum; /** * 商户类型. * * @author 丁当 * @date 2012-11-01 */ public enum CustType implements PersistentEnum<CustType, String> { FUND( "FUND", "基金" ), WINE( "WINE", "白酒" ), MALL( "MALL", "商城" ), OTHER( "OTHER", "其它" ); private String value; private final String displayName; private static Map<String, CustType> valueMap = new HashMap<String, CustType>(); static { for ( CustType _enum : CustType.values() ) { valueMap.put( _enum.value, _enum ); } } CustType( String value, String displayName ) { this.value = value; this.displayName = displayName; } public String getValue() { return value; } public String getDisplayName() { return displayName; } @Override public CustType getEnum( String value ) { return valueMap.get( value ); } @Override public Map<String, CustType> getAllValueMap() { return valueMap; } @Override public String toString() { return this.getDisplayName(); } }
4.eg.Entity
/** 类型. */ @Column( name = "TYPE" ) @Type( type = CustomEnumType.ENUM_TYPE, parameters = { @Parameter( name = "enumClass", value = "org.lop.xxx.CustType" ) } ) private CustType type;
欢迎各位指教!望出差一趟,家里平安,想家了!!!