`
dingdang_j
  • 浏览: 1893 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

扩展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;




欢迎各位指教!望出差一趟,家里平安,想家了!!!
1
0
分享到:
评论

相关推荐

    Hibernate3.2EnumTypeMapping-demo.zip

    在Hibernate3.2版本中,对枚举类型的支持得到了显著增强,引入了更优雅的映射方式。本示例代码工程"Hibernate3.2EnumTypeMapping-demo.zip"就是为了演示如何在Hibernate中正确地处理枚举类型,以提高数据模型的清晰...

    HIbernate annotation使用手册

    ### Hibernate Annotation 使用手册详解 #### 一、概述 Hibernate 是一款非常流行的 ORM(Object Relational Mapping)框架,它能够简化 Java ...同时,合理的使用这些注解也能进一步增强应用的可维护性和可扩展性。

    java笔试面试题(含有笔试题,核心技术,重点知识,struts,hibernate,spring,eclipse)

    3. **多态**:多态是指允许不同类的对象对同一消息做出响应的能力。多态可以通过方法重载和方法覆盖来实现。多态提高了代码的可扩展性,使得程序能够更加灵活地处理各种类型的对象。 #### 二、内存分析 - **堆内存...

    进入IT企业必读的324个JAVA面试题

    - 自定义异常时,可以通过扩展`Exception`类来实现。 6. **包的概念及使用**: - 包是Java中组织类的一种方式,可以避免命名冲突。 - 使用`package`声明包名,使用`import`导入其他包中的类。 7. **类与对象**...

    《基于Java的快速建站框架实现》开题报告

    5. 评估Grosbeak框架的扩展性和可维护性,以及对不同数据库的支持能力。 6. 探讨Grosbeak框架如何降低Java Web开发的学习曲线和技术门槛,使其更适合小型网站开发者使用。 通过对Grosbeak框架的深入研究,本课题...

    Java中的reflect 反射的基本东西,

    在Java中,`java.lang.reflect`包提供了对反射的支持。 反射的基础知识包括以下几个核心概念: 1. **Class对象**:每个类在运行时都有一个对应的Class对象,它包含了该类的所有信息。我们可以通过`Class.forName()...

    JAVA代码生成工具

    支持生成(gen)及删除操作(del),即生成的代码也可以很方便的删除 六. 自动删除模板扩展名: .ftl,.vm 举例: 如你有一个模板 SqlMap.xml.ftl 将变为 SqlMap.xml 所以你要生成ftl扩展名的文件,应该将文件名从 list....

    MyBatis面试宝典

    MyBatis支持多种方式来实现一对一和一对多的关系映射,包括: - **嵌套查询**:使用单独的查询来获取关联的对象。 - **嵌套结果**:通过子查询的结果来映射关联对象。 - **关联映射**:直接在主查询中通过JOIN语句...

    好用的代码生成源码

    rapid-framework是一个以spring为核心的项目脚手架(或者称为胶水框架),框架将各个零散的框架(struts,strust2,springmvc,hibernate,ibatis,spring_jdbc,flex)搭建好,并内置一个代码生成器,辅助项目开发,可以生成...

    自定义注解annotation及用法

    例如,我们可以扩展上面的`Loggable`注解,增加一个记录级别元素: ```java public @interface Loggable { String value() default ""; Level logLevel() default Level.INFO; } public enum Level { DEBUG, ...

    java基础学习词汇

    Java中有许多流行的框架,如Spring、Hibernate等。 #### Generic (泛型) 泛型是Java5引入的新特性,它允许在类、接口和方法中使用类型参数,从而编写出更加灵活且类型安全的代码。泛型可以显著减少代码重复,并...

    赣州智悦科技有限公司Java项目开发规范V1.01

    这些规范强调了良好的代码组织和命名习惯,有助于团队成员之间的代码理解与协同工作,同时也提升了系统的可扩展性和可维护性。遵循这套规范,可以确保项目结构清晰,降低因编码不一致导致的问题,从而提高整体项目...

    面试题 java方向 新版

    - 枚举(Enum):了解枚举类型在Java中的应用。 2. **集合框架** - List、Set、Queue接口:理解各种集合类的特点,如ArrayList、LinkedList、HashSet、HashMap等。 - 泛型:如何使用泛型来限制集合元素的类型。 ...

    赣州之游信息技术有限公司Java项目开发规范1

    - 映射文件目录:`mapping`存放Hibernate的hbm映射文件,`mapper`存放MyBatis的Mapper文件。 - JSP页面目录:在`WEB-INF`下的`views`,按模块划分子目录。 - 静态文件目录:`static`包含CSS、images、js、fonts和...

    java词汇.txt

    ### Java 常用词汇详解 ...以上是对Java常用词汇的一些基本介绍,这些词汇涵盖了Java编程的基础概念和技术要点,对于初学者来说是很好的入门资料。深入理解这些词汇及其背后的概念对于掌握Java编程语言至关重要。

    JAVA常用英文

    耦合,描述模块间相互依赖的程度,低耦合意味着模块独立性强,易于修改和扩展。 ### declare 声明,用于声明变量、方法、类等的存在和类型,是编写代码的第一步。 ### default 默认,指未指定时采用的值或行为,...

    java_编程常用英语单词_解释.pdf

    - **解释**: “Framework”是指一组预先定义的类和接口的集合,它们为开发特定类型的应用程序提供了结构和支持。在Java中,有许多流行的框架,如Spring、Hibernate等。 #### 38. Generic (泛型) - **拼音**: [dʒi'...

    整理后java开发全套达内学习笔记(含练习)

    extends (关键字) 继承、扩展 [ik'stend] false (关键字) final (关键字) finally (关键字) fragments 段落; 代码块 ['frægmәnt] FrameWork [java] 结构,框架 ['freimwә:k] Generic [java] 泛型 [dʒi'nerik...

Global site tag (gtag.js) - Google Analytics