别让Hibernate偷走了你的标识符

http://tech.ddvip.com   2006年11月20日    社区交流

本文详细介绍别让Hibernate偷走了你的标识符

  我们的Person对象还缺少的是equals()方法和hashCode()方法的实现。既然这是一个持久化对象,我们并不想依赖于这两个方法的缺省实现,因为缺省实现并不能分辨代表数据库中同一实体的不同实例。一种简单而又显然的实现方法是利用id字段来进行equal()方法的比较以及生成hashCode()方法的结果。

public boolean equals(Object o) {
 if (this == o) return true;
 if (o == null || !(o instanceof Person))
  return false;
 Person other = (Person)o;
 if (id == other.getId()) return true;
 if (id == null) return false;
 // equivalence by id
 return id.equals(other.getId());
}
public int hashCode() {
 if (id != null) {
  return id.hashCode();
 }
 else {
  return super.hashCode();
 }
}

  不走运的是,这个实现存在着问题。当我们首次创建Person对象的时候id的值是null,这意味着任何两个没有被保存的Person对象都将被认为是等价的。如果我们想创建一个Person对象并把它放到Set数据结构中,再创建了一个完全不同的Person对象也把它放到同一个Set里面,事实上第2个Person对象并不能被加入。这是因为Set会断定所有未经保存的对象都是相同的。

  你可能会试探着去实现一个只使用被设置过的id的equals()方法。毕竟,如果两个对象都没有被保存过,我们可以假定它们是不同的对象。这是因为在它们被保存到数据库的时候,它们会被赋予不同的主键。

  public boolean equals(Object o) {
 if (this == o) return true;
 if (o == null || !(o instanceof Person)) return false;
  Person other = (Person)o;
 // unsaved objects are never equal
 if (id == null || other.getId() == null) return false;
 return id.equals(other.getId());
}

  这里有个隐藏的问题。Java的Collection框架在它的生命周期中需要基于不变字段的equals()和hashCode()方法。换句话来说,当一个对象处在Collection中的时候,你不可以改变equals()和hashCode()的返回值。举个例子,下面这段程序:

责编:豆豆技术应用

正在加载评论...