公司框架使用的是spring mvc +spring+hibernate 各个版本都很新,hibernate主要使用的是注解映射,说实话,对开发上来说,比xml配置文件要方便得多,而且注解也支持继承,因此父类的实现可以大大降低工作量了,想以前hibernate还是配置文件的年代的时候,很多表的字段是重复固定的,如ID,创建人,创建时间等等,那个时候虽然java层面的实体可以基类,然后通过继承来减轻工作量,可是配置文件却要每个xml都复制一道(也许有方便的方式,可惜我没找到),现在有了注解,就不用这样恶心的复制了。
其实前面废话这么多,也就做个铺垫,因为这次主要说说的是hashCode与equals方法,hashCode方法很多开发人员也许不会有多少感性的认知,但是更多的人对equals方法应该很熟悉才是,hashCode方法其实与其一样,也是用于对象比较的,且其更实用(就是获得其值比较大小,很多jdk内置的一些工具的比较与排序都是使用其来完成的,因此它是一个极其重要的方法)。对于java的一些开发规范来说,对于一个java类的开发,必须实现hashCode与equals来重实现对象比较逻辑。
这次主要任务就是要实现一个hibernate映射父类的hashCode方法与equals方法,因为我并不希望每一个orm映射类都要去实现一个这样的方法,其一这没有必要,其二也为了大大减轻一些工作量,最终目的也是能够实现一个能够适用于jdk一些内置工具的orm映射体系,不会让orm对象在使用HashSet或者Map之类的工具时,让orm 对象表得奇怪。
对于表的映射orm的比较其实逻辑上多很简单,我们约定每个表的内置主键名都是id字段,因此同一个orm映射对象的比较,只要比较id就可以了,id不同的话,那么表示此对象不同,否则就相同,排序也根据其来排序。
初步的实现为下
public int hashCode() {
return id.intValue();
}
public boolean equals(Object obj) {
return this.id.longValue()==entity.id.longValue();
}
我们的id是java.lang.Long类型的,因此转换成hashCode需要intValue()一下。
但是我们实现的逻辑在父类中,也就是说,这两个方法会被其继承的子类所使用,而不同子类映射不同的表,而不同的表中所生成的主键id是完全可以相同的,在这里比对ID之前,必须比对类型,这样就可以确保对象的比对是在同一个类型下比较的,于是在之前加入如下代码:
public int hashCode() {
int id=this.id==null?0:this.id.intValue();
return id^this.getClass().getName().hashCode();
}
public boolean equals(Object obj) {
if(!this.getClass().getName().equals(obj.getClass().getName())){
return false;
}
return this.id.longValue()==entity.id.longValue();
}
这里为什么不直接比较Class,而要比较Class对象的name属性,因为Class没有自己实现hashCode方法与equals方法,且某个类的Class对象在虚拟机中也不一定会是单例的,因为同样的类可能由不同的类装载器完成装载,这样在虚拟机中就会存在两个完全相同的类的Class对象,而且这两个对象会在一些时候碰头,最典型的例子就是你用oracle驱动包中的Timestamp的class模板去比较一个由jdbc装载的一个Timestamp对象的getClass的模板,你会发现它们的全限定名完全相同,但是equals却返回false。因此此处必须比较name,因为name转换为String,比较是不会出现歧义的。
在使用一段时间后,又发现问题,比较类模板也是不行的,这是因为hibernate的延迟加载机制的缘故,因为延迟加载改变了原始的类模板,使用了重新生成的代理类,这时,我们自己生产的对象与hibernate装载的对象,我们自以为是相同的,但实际却不同,因为我们使用的类模板是原始类模板,而hibernate装载的却是修改过的代理类模板,如此一来,简单的类模板比对则无用了,后来经过我冥思苦想,终于找到一个替代性的办法,也许这个方式并不成熟,因为我们使用的是注解,因此我打算利用注解的@Table的name属性来完成比对(我们规定每个orm映射都要指定表名,因此这种方式对我们的系统来说可行的),如今代码如下,这是先行版的完整代码:
public int hashCode() {
String tableName=this.tableName();
int id=this.id==null?0:this.id.intValue();
if(StringUtils.isNotBlank(tableName)){
return id^tableName.hashCode();
}else{
return id^this.getClass().hashCode();
}
}
public boolean equals(Object obj) {
if(obj==null){
return false;
}
if(!(obj instanceof IdEntity)){
return false;
}
IdEntity entity=(IdEntity) obj;
if(this.id==null||entity.id==null){
return false;
}
boolean typecheck=false;
if(StringUtils.isNotBlank(this.tableName())){
this.tableName().equals(entity.tableName());
}else{
typecheck=this.entityName().equals(entity.entityName());
}
return (this.id.longValue()==entity.id.longValue())&&typecheck;
}
里面实现了一些equals的一些其它标准。
分享到:
相关推荐
MySQL数据库表映射实体生成是一种常见的开发任务,特别是在Java企业级应用中,它涉及到ORM(对象关系映射)技术,如Hibernate或MyBatis。这个工具类的目标是自动化将数据库中的表结构转换为编程语言中的实体类,这样...
将JSON列类型映射到List或Map<String> ,需要确保POJO类型覆盖默认的equals和hashCode方法,并根据JSON对象的内容实现它们。 否则,Hibernate脏检查机制可能会触发意外的UPDATE语句。 查看。 Oracle 您应该使用...
“Persistent Classes”部分讨论了持久化类的设计准则,包括简单的POJO示例、继承的实现、equals()和hashCode()方法的重写、动态模型的应用、Tuplizers的概念等。这些原则有助于开发者编写出既符合Hibernate规范又...
3. **equals()和hashCode()方法**:解释了在使用集合时,持久化类需要正确覆盖equals()和hashCode()方法。 4. **动态模型和元组片断映射**:讨论了如何实现动态的ORM模型,以及如何使用元组片断映射到不同的数据库...
Hibernate是一种“对象/关系映射”(Object/Relational Mapping,简称ORM)技术,它解决了Java对象模型与关系数据库模型之间的不匹配问题。传统的数据库编程需要在代码中直接编写SQL语句,而Hibernate通过提供一个...
- **继承的实现、equals()和hashCode()方法的实现、动态模型、Tuplizers、实体名称解析器**: 这些是更高级的ORM概念,说明了如何在Hibernate中实现继承、对象比较以及在运行时处理对象模型的变化。 - **Hibernate...
通过上述对几个常见 Hibernate 错误的解析及解决方法的介绍,我们可以发现大部分问题都与配置文件的设置、实体类的定义以及事务管理有关。在日常开发中,我们应该注意这些细节,以避免不必要的错误发生。同时,对于...
在处理视图时,注意的一个关键点是,由于视图没有主键,Hibernate可能会在生成的POJO类中自定义一个复合键类,如`TestId`,并实现`equals()`和`hashCode()`方法。这两个方法对于集合类的正确操作至关重要,比如在...
- **4.3 实现 equals() 和 hashCode() 方法** 为了确保 Hibernate 正确处理对象的唯一性,需要为持久化类实现这两个方法。 - **4.4 动态模型** 介绍如何使用 Hibernate 的动态元数据映射来处理结构不确定的数据...
- 必要时,还需要重写 `equals` 和 `hashCode` 方法以支持某些特定操作。 3. **创建对象-关系映射文件**: - 映射文件采用 XML 格式,用于指定 Java 类和数据库表之间的映射关系。 - 包括类-表映射、属性-字段...
在持久化类部分,文档讲解了如何设计符合Hibernate规范的Java类,包括POJO的实现、继承机制、equals()和hashCode()方法的重写,以及持久化生命周期中的回调。此外,XDoclet标记示例展示了如何利用注解简化映射过程。...
- **equals()与hashCode()方法**:为了正确的对象比较和哈希计算,需要正确实现这两个方法。 - **动态模型**:使用动态代理技术来支持动态创建的实体类。 - **元组片段映射**:介绍了一种特殊的映射机制,用于更...
关于“PersistentClasses”,文档提供了如何创建简单的POJO示例以及实现继承、equals()和hashCode()方法的指南。还介绍了动态模型的使用、tuplizers的应用,这些都是Hibernate高级特性的一部分,对于实现复杂对象...
- **实现equals()和hashCode()方法**:确保实体对象正确比较和存储。 - **动态模型**:动态生成实体类的机制。 - **元组片段映射**:高级映射技术之一。 5. **对象/关系数据库映射基础** - **映射定义**:包括...
- **实现 equals() 和 hashCode()**:确保持久化类正确实现这两个方法以支持对象比较。 #### 五、基本 ORM 映射 - **映射声明**:讲解如何在映射文件中声明实体及其属性。 - **实体**:定义 Hibernate 中的基本映射...