实现equals()和hashCode()
2013-01-06 14:32
148 查看
如果你有如下需求,你必须重载 equals() 和 hashCode()方法:
想把持久类的实例放入Set中(当表示多值关联时,推荐这么做)
想重用脱管实例
Hibernate保证,持久化标识(数据库的行)和仅在特定会话范围内的Java标识是等值的。因此,一旦 我们混合了从不同会话中获取的实例,如果我们希望Set有明确的语义,我们必 须实现equals() 和hashCode()。
实现equals()/hashCode()最显而易见的方法是比较两个对象 标识符的值。如果值相同,则两个对象对应于数据库的同一行,因此它们是相等的(如果都被添加到Set,则在Set中只有一个元素)。不幸的是,对生成的标识不能 使用这种方法。Hibernate仅对那些持久化对象赋标识值,一个新创建的实例将不会有任何标识值。此外,
如果一个实例没有被保存(unsaved),并且在一个Set中,保存它将会给这个对象 赋一个标识值。如果equals() 和hashCode()是基于标识值 实现的,则其哈希码将会改变,违反Set的契约。建议去Hibernate的站点看关于这个 问题的全部讨论。注意,这不是一个Hibernate问题,而是一般的Java对象标识和相等的语义问题。
我们建议使用业务键值相等(Business key equality)来实现equals() 和hashCode()。业务键值相等的意思是,equals()方法 仅仅比较来自业务键的属性,一个业务键将标识在真实世界里(一个天生的候选键)
的实例。
注意,业务键不必是象数据库的主键那样是固定不变的。 对业务键而言,不可变或唯一的属性是好的候选。
想把持久类的实例放入Set中(当表示多值关联时,推荐这么做)
想重用脱管实例
Hibernate保证,持久化标识(数据库的行)和仅在特定会话范围内的Java标识是等值的。因此,一旦 我们混合了从不同会话中获取的实例,如果我们希望Set有明确的语义,我们必 须实现equals() 和hashCode()。
实现equals()/hashCode()最显而易见的方法是比较两个对象 标识符的值。如果值相同,则两个对象对应于数据库的同一行,因此它们是相等的(如果都被添加到Set,则在Set中只有一个元素)。不幸的是,对生成的标识不能 使用这种方法。Hibernate仅对那些持久化对象赋标识值,一个新创建的实例将不会有任何标识值。此外,
如果一个实例没有被保存(unsaved),并且在一个Set中,保存它将会给这个对象 赋一个标识值。如果equals() 和hashCode()是基于标识值 实现的,则其哈希码将会改变,违反Set的契约。建议去Hibernate的站点看关于这个 问题的全部讨论。注意,这不是一个Hibernate问题,而是一般的Java对象标识和相等的语义问题。
我们建议使用业务键值相等(Business key equality)来实现equals() 和hashCode()。业务键值相等的意思是,equals()方法 仅仅比较来自业务键的属性,一个业务键将标识在真实世界里(一个天生的候选键)
的实例。
public class Cat { ... public boolean equals(Object other) { if (this == other) return true; if ( !(other instanceof Cat) ) return false; final Cat cat = (Cat) other; if ( !cat.getLitterId().equals( getLitterId() ) ) return false; if ( !cat.getMother().equals( getMother() ) ) return false; return true; } public int hashCode() { int result; result = getMother().hashCode(); result = 29 * result + getLitterId(); return result; } }
注意,业务键不必是象数据库的主键那样是固定不变的。 对业务键而言,不可变或唯一的属性是好的候选。
相关文章推荐
- Set是如何实现元素不重复的&重写equals()方法之后也必须重写hashCode()方法
- java -- 为什么我们需要实现hashCode和equals
- 使用EqualsBuilder和HashCodeBuilder实现hashCode()和equals()方法
- 默认实现了equals,hashcode,tostring方法的pojo基类
- 8_实现Serializable接口_重写equals和hashCode方法
- java对象通用方法之覆盖equals时请遵守通用约定、覆盖equals时总要覆盖hashCode、始终要覆盖toString、考虑实现Comparable接口
- Effective java 对像引用和hashcode和equals方法实现
- 采用commons-lang.jar包实现equals,hashCode以及toString方法
- 重写equals()与hashcode()方法,及comparable接口的实现
- HashSet的对象必须实现hashCode()和equals()
- JDK源码之解读String最终类的equals()和hashcode()方法实现原理
- HashMap与HashCode()、equals()的关系---在HashMap中实现以对象为键(key)
- JDK源码之解读String最终类的equals()和hashcode()方法实现原理
- NO8-10 实现高质量的equals方法,hashCode()方法,toString()方法
- 两种简单的方式快速实现hashCode 和 equals方法
- ID的生成策略(hibernate的id生成策略,主键类为什么需要实现序列化接口,同时还要重写hashCode()和equals()方法)
- hibernate中提倡持久类实现equals()和hashCode()分析
- hibernate中提倡持久类实现equals()和hashCode()的原因分析
- 【原创】关于hashcode和equals的不同实现对HashMap和HashSet集合类的影响的探究
- hibernate中提倡持久类实现equals()和hashCode()的原因分析