您的位置:首页 > 其它

实现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()方法 仅仅比较来自业务键的属性,一个业务键将标识在真实世界里(一个天生的候选键)
的实例。

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;
}

}


注意,业务键不必是象数据库的主键那样是固定不变的。 对业务键而言,不可变或唯一的属性是好的候选。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐