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

Hibernate user type with Annotation - 话题延续

阅读更多
前段时间写了一篇介绍hibernate user type的文章: http://www.iteye.com/topic/214145,很长时间没有看了,最近发现有人回帖说:

downpour 写道
http://www.hibernate.org/272.html

hibernate官方论坛早有实现。还是通用的GenericEnumUserType。不是很明白,为什么碰到问题总是喜欢自己实现,而不去google一下别人早已实现了很多遍并经过实践证明的东西。


本想跟贴继续讨论,可是写着写着发现内容比较多,就干脆开个新贴讨论吧,想知道前因的朋友请去看前一个帖子。

好,下面开始本帖的正式话题:

downpour说的官方实现我也知道,我写这个UserType是出于如下考虑:

1. 当然是为了讲解如何编写自定义的hibernate UserType。
2. 为enum定义通用接口便于编写通用util方法(后面会展开讲)。

首先我得承认,对比我这个实现,官方的GenericEnumUserType覆盖面更广,但是使用的时候也有如下不足之处:

1. 需要处理的parameter太多。针对我这个例子,如果要使用GenericEnumUserType的话,注释就得这么写:
@org.hibernate.annotations.TypeDef(
		name = "status", 
		typeClass = de.besitec.octopus.domain.support.GenericEnumUserType.class, 
						parameters = { 
@org.hibernate.annotations.Parameter(
                name = "enumClass", 
		value = "com.yourpackage.Status"), 
@org.hibernate.annotations.Parameter(
		name = "identifierMethod", 
		value = "getId"),
@org.hibernate.annotations.Parameter(
		name = "valueOfMethod", 
		value = "findEnumById"),
								})

而且status类中的id变量必须为Integer。

对于少量的Enum或者是通用的Enum(注释可以写到package-info.java里面去)还好说。一旦enum的数量一多,使用起来岂不是比我的方案麻烦很多?

2. 性能相对较差。GenericEnumUserType实现里调用的反射方法比我写的这个要多,大家知道调用反射方法要比正常的方法调用慢大概10倍左右,如果系统中enum比较多,全部使用这个UserType的话,应该对性能有一定的影响。这一点只是猜测,具体我没有测试,如果有朋友有兴趣测试的话,请告诉我结果,不过请注意,测试的前提是enum比较多。

3. 持久化enum的特例毕竟有限,我们目前的系统除了要保存老的标识符(int)或者是该enum的描述(String)以外,还没有碰到其他的特例,因此编写两个UserType就足够了。日后同事使用起来也方便,毕竟需要的parameter要少很多。

至于为什么说“为enum定义通用接口便于编写通用helper方法”呢?解释起来要费点唇舌,让我们先回过头来看看status的代码:

public   enum  Status  implements  DescriptionID {

	OPEN(5, "This object is activated"), 
	CLOSED(9, "This object is deactivated");

	private int id;
	private String description;

	private Status(int statusNr, String description) {
		this.id = statusNr;
		this.description = description;
	}

	public String getDescription() {
		return this.description;
	}

	public int getId() {
		return id;
	}

	public static List<Status> getAll() {
	      return Arrays.asList(Status.class.getEnumConstants());
	}

        public static  Status findById(Integer id) {
         for  (Status status : getAll()) {
             if  (id  ==  status.getId()) {
                 return  status;
            }
        }
         return   null ;
    }
 }


注意,在老帖子里getAll()写的不好,这里已经纠正了。

仔细看一下status的代码,我们会发现每一个类似的enum类都必须要写findById()这个方法,里面的逻辑代码是完全一样的,完全可以提出到一个util类中去。如果不定义通用接口的话,就必须要用反射来编写。前面说了,过度使用反射会带来性能问题,因此这里建议使用通用接口。

Okay,针对我们这个例子,EnumUtils可以这么些
public class EnumUtils {

	public static <I extends DescriptionID> I getEnum(Class<I> type, int id) {
		I[] types = type.getEnumConstants();
		for (I t : types) {
			if (t.getId() == id)
				return t;
		}
		throw new AssertionError("unable to map: " + id + " to enum: "
				+ type.getSimpleName());
	}
	
	public static <I extends DescriptionID> I getEnum(Class<I> type, String description) {
		I[] types = type.getEnumConstants();
		for (I t : types) {
			if (StringUtils.equals(t.getDescription(), description))
				return t;
		}
		throw new AssertionError("unable to map: " + description + " to enum: "
				+ type.getSimpleName());
	}

	/**
	 * @param <I>
	 * @param type
	 * @return the enum description list
	 */
	public static <I extends DescriptionID> List<String> getDescriptions(Class<I> type) {
		I[] types = type.getEnumConstants();
		List<String> result = new ArrayList<String>(types.length);
		for (I t : types) {
			result.add(t.getDescription());
		}
		return result;
	}
}

三个方法一次为:
1. 根据所给id返回对应enum实例.
2. 根据所给Description返回对应enum实例.
3. 返回所有enum实例的description.

其他方法大家可以自由发挥。

那个静态的findById()方法仍然可以保留,不过逻辑代码已经全部移出:

	public static Status getEnumById(Integer id) {
		return EnumUtils.getEnum(Status.class, id);
	}
分享到:
评论
3 楼 china_volcano 2009-11-25  
studying......
2 楼 打倒小日本 2009-10-20  
JPA默认提供的@Enumerated注解不能解决这个问题么?

对于枚举类型 我们一般这样写就OK了

@Enumerated(EnumType.STRING)
public SexKey getSex() {
	return sex;
}

public void setSex(SexKey sex) {
	this.sex = sex;
}


难道是我没理解楼主的意思?
1 楼 sunshan 2009-10-18  
这个方法不错!

相关推荐

    hibernate-validator-annotation-processor-4.3.1.final-sources.jar.zip

    这个压缩包“hibernate-validator-annotation-processor-4.3.1.final-sources.jar.zip”包含了Hibernate Validator注解处理器的源代码,版本号为4.3.1.Final,是理解其内部工作原理和自定义验证规则的重要资源。...

    hibernate-validator-annotation-processor-5.1.0.CR1.zip

    【标题】"Hibernate Validator Annotation Processor 5.1.0.CR1" Hibernate Validator 是一个流行的开源验证框架,它基于JSR 303/JSR 349(Bean Validation)标准,为Java应用程序提供了强大的数据验证功能。...

    jakarta.annotation-api-1.3.5-API文档-中文版.zip

    赠送jar包:jakarta.annotation-api-1.3.5.jar; 赠送原API文档:jakarta.annotation-api-1.3.5-javadoc.jar; 赠送源代码:jakarta.annotation-api-1.3.5-sources.jar; 赠送Maven依赖信息文件:jakarta.annotation...

    javax.annotation-api-1.3.2-API文档-中文版.zip

    赠送jar包:javax.annotation-api-1.3.2.jar; 赠送原API文档:javax.annotation-api-1.3.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.3.2-sources.jar; 赠送Maven依赖信息文件:javax.annotation-api-...

    javax.annotation-api-1.2-API文档-中文版.zip

    赠送jar包:javax.annotation-api-1.2.jar; 赠送原API文档:javax.annotation-api-1.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.2-sources.jar; 赠送Maven依赖信息文件:javax.annotation-api-1.2.pom;...

    jakarta.annotation-api-1.3.5-API文档-中英对照版.zip

    赠送jar包:jakarta.annotation-api-1.3.5.jar; 赠送原API文档:jakarta.annotation-api-1.3.5-javadoc.jar; 赠送源代码:jakarta.annotation-api-1.3.5-sources.jar; 赠送Maven依赖信息文件:jakarta.annotation...

    hibernate-validator-5.0.0.CR2-dist.zip

    使用hibernate-validator 进行校验的jar包,里面包括了基础hibernate-validator-5.0.0.CR2.jar hibernate-validator-annotation-processor-5.0.0.CR2.jar 之外,还包括了el-api-2.2.jar javax.el-2.2.4等项目必不可...

    hibernate-annotation-helloword

    **hibernate-annotation-helloworld** 是一个基于Hibernate框架,使用注解方式实现的Hello World示例项目。在Java世界中,Hibernate是一个流行的持久层框架,它极大地简化了数据库操作,尤其是在对象关系映射(ORM)...

    javax.annotation-api-1.3.2 jar包.rar

    `javax.annotation-api-1.3.2.jar` 包是Java标准版(Java SE)中的一个关键组件,它包含了用于开发和实现注解的API。这个API主要用于提供一些预定义的注解,这些注解可以增强代码的功能性和可维护性,同时减少对传统...

    point-cloud-annotation-tool

    github链接链接:https://github.com/springzfx/point-cloud-annotation-tool 在windows平台编译完成后的exe和dll文件,可以直接打开使用,并对原项目进行了优化,增加了列表和标注文件的显示功能,标注起来更快,...

    javax.annotation-api-1.3.2

    JDK9及以上版本没有javax.annotation-api-***.jar包 ,无法使用注解:@Resource JDK新特性,高版本JDK没有自带的javax(java扩展包)了。或者是使用的JDK不完整。 下载javax.annotation.jar包,导入到lib文件夹下,...

    javax.annotation-api-1.3.2-API文档-中英对照版.zip

    赠送jar包:javax.annotation-api-1.3.2.jar; 赠送原API文档:javax.annotation-api-1.3.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.3.2-sources.jar; 包含翻译后的API文档:javax.annotation-api-...

    拦截器与冲突解决

    然而,在使用`&lt;mvc:annotation-driven /&gt;`元素时,有时会出现与自定义拦截器的冲突问题。这个问题通常出现在当我们试图同时配置基于注解的控制器处理和自定义拦截器时,Spring可能无法正确地处理这些组件的执行顺序...

    point-cloud-annotation-tool win10解压直接运行

    "point-cloud-annotation-tool" 提供了在Windows 10操作系统上直接进行点云注解的能力,无需复杂的安装过程,只需解压即可运行。 1. 点云标注工具介绍: 点云标注工具是专门用于标记和分类点云数据的软件,它可以...

    javax.annotation-api-1.2-API文档-中英对照版.zip

    赠送jar包:javax.annotation-api-1.2.jar; 赠送原API文档:javax.annotation-api-1.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.2-sources.jar; 赠送Maven依赖信息文件:javax.annotation-api-1.2.pom;...

    androidx-annotation-1.2.0.jar

    androidx-annotation-1.2.0.jar

    hibernate-annotation

    《深入理解Hibernate注解》 Hibernate作为Java领域中的一款强大持久化框架,极大地简化了数据库操作。而Hibernate注解则是其在ORM(对象关系映射)领域的进一步进化,它允许开发者将元数据直接嵌入到Java类和属性的...

    spring的annotation-driven配置事务管理器详解 (多数据源配置

    Spring 的 Annotation-Driven 配置事务管理器详解(多数据源配置) Spring 框架提供了强大的事务管理机制,通过使用 Annotation-Driven 配置,可以方便地管理事务。在多数据源配置中,spring 的 Annotation-Driven...

    androidx-annotation-1.0.0.jar

    androidx-annotation-1.0.0.jar

    javax.annotation-api-1.2.jar

    javax.annotation-api-1.2.jar包,注解,声明,@Resource是做bean的注入使用。

Global site tag (gtag.js) - Google Analytics