簡述Hibernate兩種方法的實現
Hibernate有很多方法,每一種方法都有自己實現的過程,這里詳述Hibernate兩種方法的實現Hibernate equals()和Hibernate hashCode()。
實現Hibernate equals()和hashCode()如果你有如下需求,你必須重載 equals() 和 hashCode()方法:
想把持久類的實例放入Set中(當表示多值關聯時,推薦這么做)
想重用脫管實例
Hibernate保證,僅在特定會話范圍內,持久化標識(數據庫的行)和Java標識是等價的。因此,一旦 我們混合了從不同會話中獲取的實例,如果希望Set有明確的語義,就必 須實現equals() 和hashCode()。
實現Hibernate equals()/HibernatehashCode()最顯而易見的方法是比較兩個對象標識符的值。如果值相同,則兩個對象對應于數據庫的同一行,因此它們是相等的(如果都被添加到 Set,則在Set中只有一個元素)。
不幸的是,對生成的標識不能 使用這種方法。Hibernate僅對那些持久化對象賦標識值,一個新創建的實例將不會有任何標識值。此外, 如果一個實例沒有被保存(unsaved),并且它當前正在一個Set中,保存它將會給這個對象 賦一個標識值。
如果Hibernate equals() 和Hibernate hashCode()是基于標識值 實現的,則其哈希碼將會改變,這違反了Set的契約。建議去Hibernate的站點閱讀關于這個 問題的全部討論。
注意:這不是Hibernate的問題,而是一般的Java對象標識和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;
- }
- }
注意:
業務鍵不必像數據庫的主鍵那樣固定不變。對業務鍵而言,不可變或唯一的屬性是不錯的選擇。
【編輯推薦】