若使用過Set,你會知道Set中是不允許存儲重復值的,這也是為什麼Hibernate推薦在多表關聯的映射中采用Set作為存儲實體對象的主要原因。在多表關聯映射中的持久類中,常見如下代碼:
private Set<?> sysUsersRoles = new HashSet(0);
private Set<?> sysRolesAuthorities = new HashSet(0);
public Set getSysUsersRoles() {
return this.sysUsersRoles;
}
public void setSysUsersRoles(Set sysUsersRoles) {
this.sysUsersRoles = sysUsersRoles;
}
public Set getSysRolesAuthorities() {
return this.sysRolesAuthorities;
}
public void setSysRolesAuthorities(Set sysRolesAuthorities) {
this.sysRolesAuthorities = sysRolesAuthorities;
}
按照Hibernate的提倡,應該在該持久化類裡,重寫equals()和hashCode()方法。那麼為什麼要對這兩個方法進行重寫呢? Set裡面不是不允許有重復的值嗎?
重寫這兩個方法究竟能起到什麼作用?equals()和hashCode()的意義究竟是什麼?
這是我看到Hibernate提倡的重寫這兩個方法之後我的疑問!
不妨先來探討一下equals()和hashCode()的作用吧。
實際上,equals()和hashCode()這兩個方法存在的意義是為瞭區別對象。這兩個方法均來自於Object類。
在對象運行期間,為瞭在運行期區別各對象,就是通過這兩個方法,它們之間的區別如下:
1.Object類的public boolean equals(Object obj)方法是通過 return this == obj;這種方式比較兩個對象是否相同。這裡比較的是引用。
2.Object類的public int hashCode()方法,是通過該實例地址轉換為int值。所以不同的Object實例在同一運行期hashCode一定不相同。
現在解決瞭equals()和hashCode()是什麼以及什麼作用的問題。
那麼再來談談Hibernate的運行機理吧:
在Hibernate的運行期內,通過find或者其他方式提取的對象列表,在不同上下文的操作中,或者在瞬時、持久、脫管三種狀態的變換中,為瞭避免類名相同,但對象內容不同的實例互相碰撞造成混亂,就需要采用更加準確的區別對象的方法,而此時的equals()和hashCode()已經不能滿足要求,隻有對這兩個方法進行重寫,增加對這些持久類的各屬性的內容進行區分,才能真正區分從Hibernate的find方法中提取的對象。
那麼什麼樣的實例才算是相同的呢? 當然除瞭你的持久類名標識之外,還需要明確的標識出持久化實例中某些屬性的值也是相等的,兩個實例才算是真正相同。
比如以下兩行數據來自於Person表(字段內容包括ID,姓名name,年齡age,父親姓名fartherName),這是實例相同的例證:
1,王長江,30,王有才;
1,王長江,30,王有才;
以下兩行實例是不相同的例證:
1,王長江,30,王有才;
1,王長江,30,王有財;
哈哈,看出區別來瞭嗎? 隻有一字隻差,就會在Hibernate管理的實例中被看作兩個實例,這就是你重寫hashCode()的重要作用。
順便將重寫的hashCode()和equals()也寫在下面吧:
public boolean equals( Object other ){
if( this == other ) return true;
if( !( other instanceof Person ) ) return false;
final Person person = (Person)other;
if( !person.getName().equals( getName() ) ) return false;
if( !person.getAge().equals( getAge())) return false;
if( !person.getFartherName().equals( getFartherName())) return false;
return true;
}
public int hashCode(){
int result;
result = getName().hashCode();
result = 29 * result + getAge();
result = 29 * result + getFartherName();
return result;
}
還有,朋友們也可以鍵入以下代碼嘗試一下兩者的區別:
public static void main(String[] args){
SysRoles role1 = new SysRoles(“1″,”lxb”,”ljh”);
SysRoles role2 = new SysRoles(“1″,”lxb”,”ljh”);
/**//*
* 經過試驗,當不重寫equals和hashCode時顯示為false;
* 重寫時,顯示為true。
* 這就是為什麼重寫equals和hashCode的原因,當你希望從hiberate中提取的對象實例中,
* 若是所有字段的內容都相同,就認為這兩個對象實例是相同的,此時就需要重寫equals和hashCode。
* 重寫equals和hashCode意味著,混雜在不同上下文及Session中的兩個實例對象有瞭確定的語義。
*/
System.out.println(role1.equals(role2));
/**//*
* 經過試驗,當不重寫equals和hashCode時顯示為false;
* 重寫時,顯示為true。
*
*/
System.out.println(role1.hashCode() == role2.hashCode());
}
哈哈,朋友們自己總結一下吧!