Hibernate並不保證不同時間所取得的資料物件,其是否參考至記憶體的同一位置,使用==來比較兩個物件的資料是否代表資料庫中的同一筆資料是不可行的,而Object預設的equals()本身即比較物件的記憶體參考,如果您要有必要比較透過查詢後兩個物件的資料是否相同(例如當物件被儲存至Set時)您必須實作equals()與hashCode()。
一個實作equals()與hashCode()的方法是根據資料庫的identity,一個方法是透過getId()方法取得物件的id值並加以比較,例如若id的型態是String,一個實作的例子如下:
User.java
public class User {
....
public boolean equals(Object o) {
if(this == o) return true;
if(id == null || !(o instanceof User)) return false;
final User user == (User) o;
return this.id.equals(user.getId());
}
public int hasCode() {
return id == null ? System.identityHashCode(this) : id.hashcode();
}
}
這個例子取自於Hibernate in Action第123頁的範例,然而這是個不被鼓勵的例子,因為當一個物件被new出來而還沒有save()時,它並不會被賦予id值,這時候就不適用這個方法。
一個比較被採用的方法是根據物件中真正包括的的屬性值來作比較,在參考手冊中給了一個例子:
Cat.java
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 (!getName().equals(cat.getName())) return false;
if (!getBirthday().equals(cat.getBirthday())) return false;
return true;
}
public int hashCode() {
int result;
result = getName().hashCode();
result = 29 * result + getBirthday().hashCode();
return result;
}
}
我們不再簡單的比較id屬性,這是一個根據商務鍵值(business key)實作equals()與hasCode()的例子,當然留下的問題就是您如何在實作時利用相關的商務鍵值,這就要根據您實際的商務需求來決定了。