2025-05-23

若使用過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());
       
}
   
    哈哈,朋友們自己總結一下吧!



 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *