Java程式員從笨鳥到菜鳥之(六十)細談Hibernate(十一)hibernate複合主鍵映射

來源:互聯網
上載者:User

               歡迎閱讀本專題其他部落格:     

                                                         細談Hibernate(六)Hibernate繼承關係映射

 

                                   細談Hibernate(七)Hibernate自身一對多和多對多

 

                                    細談Hibernate(八)Hibernate集合Map關係映射

 

                                   細談Hibernate(九)hibernate一對一關聯性映射

 

                                  細談Hibernate(十)hibernate查詢排序和組件映射

 

          所謂複合主鍵就是在一張資料庫表中,主鍵有兩個或者多個,在日常開發中會遇到這樣一種情況,資料庫中的某張表需要多個欄位列才能唯一確定一行記錄,這時表需要使用複合主鍵。這是我們以前在hibernate配置中沒有遇到過的情況。面對這樣的情況Hibernate為我們提供了兩種方式來解決複合主鍵問題,下面讓我們來看一下這兩種情況:

 

1:將複合主鍵對應的屬性與實體其他普通屬性放在一起

2:將主鍵屬性提取到一個主鍵類中,實體類只需包含主鍵類的一個引用

 

 下面我們就具體來看一下:

 

方式一:將複合主鍵對應的屬性與實體其他普通屬性放在一起

例如實體類People中"id"和"name"屬性對應複合主鍵:

 

/*實體類,使用複合主鍵必須實現Serializable介面*/public class People implements Serializable{    private String id;    private String name;    private int age;        public People()    { }***************set、get方法    public int hashCode()    {        final int prime = 31;        int result = 1;        result = prime * result + ((id == null) ? 0 : id.hashCode());        result = prime * result + ((name == null) ? 0 : name.hashCode());        return result;    }    @Override    public boolean equals(Object obj)    {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        People other = (People) obj;        if (id == null)        {            if (other.id != null)                return false;        }        else if (!id.equals(other.id))            return false;        if (name == null)        {            if (other.name != null)                return false;        }        else if (!name.equals(other.name))            return false;        return true;    }}

 

People.hbm.xml:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.suxiaolei.hibernate.pojos.People" table="people">        <!-- 複合主鍵使用composite-id標籤 -->        <composite-id>            <!-- key-property標籤表示哪一些屬性對應複合主鍵 -->            <key-property name="id" column="id" type="string"></key-property>            <key-property name="name" column="name" type="string"></key-property>        </composite-id>        <property name="age" column="age" type="integer"></property>    </class></hibernate-mapping>

Hibernate中使用複合主鍵時需要注意一些規則:

1. 使用複合主鍵的實體類必須實現Serializable介面。必須實現Serializable介面的原因很簡單,我們尋找資料的時候是根據主鍵尋找的。開啟Hibernate的協助文檔我們可以找到get與load方法的聲明形式如下:

Object load(Class theClass,Serializable id)Object get(Class theClass,Serializable id)

       當 我們尋找複合主鍵類的對象時,需要傳遞主索引值給get()或load()方法的id參數,而id參數只能接收一個實現了Serializable介面的對 象。而複合主鍵類的主鍵不是一個屬性可以表示的,所以只能先new出複合主鍵類的執行個體(例如:new People()),然後使用主鍵屬性的set方法將主索引值賦值給主鍵屬性,然後將整個對象傳遞給get()或load()方法的id參數,實現主索引值的 傳遞,所以複合主鍵的實體類必須實現Serializable介面。

 

2. 使 用複合主鍵的實體類必須重寫equals和hashCode方法。必須重寫equals和hashCode方法也很好理解。這兩個方法使用於判斷兩個對象 (兩條記錄)是否相等的。為什麼要判斷兩個對象是否相等呢?因為資料庫中的任意兩條記錄中的主索引值是不能相同的,所以我們在程式中只要確保了兩個對象的主 索引值不同就可以防止主鍵約束違例的錯誤出現。也許這裡你會奇怪為什麼不使用複合主鍵的實體類不重寫這兩個方法也沒有主鍵違例的情況出現,這是因為使用單一
主鍵方式,主索引值是Hibernate來維護的,它會確保主鍵不會重複,而複合主鍵方式,主索引值是編程人員自己維護的,所以必須重寫equals和hashCode方法用於判斷兩個對象的主鍵是否相同。

 

3. 重寫的equals和hashCode方法,只與主鍵屬性有關,普通屬性不要影響這兩個方法進行判斷。這個原因很簡單,主鍵才能決定一條記錄,其他屬性不能決定一條記錄。

 

儲存測試:

            

tx = session.beginTransaction();                        People people = new People();            /*主索引值由我們自己維護*/            people.setId("123456");            people.setName("zhangsan");            people.setAge(40);            session.save(people);tx.commit();

      

看看資料庫:

資料被正確的插入到資料庫中了。

 

讀取資料測試:

      

 tx = session.beginTransaction();            /*查詢複合主鍵對象,需要先構建主鍵*/            People peoplePrimaryKey = new People();            peoplePrimaryKey.setId("123456");            peoplePrimaryKey.setName("zhangsan");                        /*然後將構建的主索引值傳入get方法中擷取對應的People對象*/            People people = (People)session.get(People.class, peoplePrimaryKey);            System.out.println("people age is:"+people.getAge());            tx.commit();

控制台輸出:people age is:40,以看到資料成功的取出了。

 

方式二:將主鍵屬性提取到一個主鍵類中,實體類只需包含主鍵類的一個引用。

主鍵類:

/*必須實現Serializable介面*/public class PeoplePrimaryKey implements Serializable{    /*複合主索引值*/    private String id;    private String name;        public PeoplePrimaryKey()    {}        /*複合主索引值的get和set方法在此省略*/   @Override    public int hashCode()    {        final int prime = 31;        int result = 1;        result = prime * result + ((id == null) ? 0 : id.hashCode());        result = prime * result + ((name == null) ? 0 : name.hashCode());        return result;    }    @Override    public boolean equals(Object obj)    {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        PeoplePrimaryKey other = (PeoplePrimaryKey) obj;        if (id == null)        {            if (other.id != null)                return false;        }        else if (!id.equals(other.id))            return false;        if (name == null)        {            if (other.name != null)                return false;        }        else if (!name.equals(other.name))            return false;        return true;    }}

實體類:

public class People{    /*持有主鍵類的一個引用,使用該引用作為這個類的OID*/    private PeoplePrimaryKey peoplePrimaryKey;    private int age;        public People()    {}    ***************************set/get方法省略}

 

People.hbm.xml檔案稍有一點變動:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.suxiaolei.hibernate.pojos.People" table="people">        <!-- 複合主鍵使用composite-id標籤 -->        <!--        name - 指定了複合主鍵對應哪一個屬性        class - 指定了複合主鍵屬性的類型        -->        <composite-id name="peoplePrimaryKey" class="com.suxiaolei.hibernate.pojos.PeoplePrimaryKey">            <!-- key-property指定了複合主鍵由哪些屬性群組成 -->            <key-property name="id" column="id" type="string"></key-property>            <key-property name="name" column="name" type="string"></key-property>        </composite-id>        <property name="age" column="age" type="integer"></property>    </class></hibernate-mapping>

       情境測試與方式一大同小異這裡不再舉例了。主鍵類為什麼實現Serializable介面和為什麼重寫equals和hashCode方法上面已經解釋的很清楚了。

 

3.聯合主鍵的映射規則

1) 類中的每個主鍵屬性都對應到資料表中的每個主鍵列。Hibernate要求具有聯合主鍵的實體類實現Serializable介面,並且重寫hashCode與equals方法,重寫這兩個方法的原因在於Hibernate要根據資料庫的聯合主鍵來判斷某兩行記錄是否是一樣的,如果一樣那麼就認為是同一個對象,如果不一樣,那麼就認為是不同的對象。這反映到程式領域中就是根據hashCode與equals方法來判斷某兩個對象是否能夠放到諸如Set這樣的集合當中。聯合主鍵的實體類實現Serializable介面的原因在於使用get或load方法的時候需要先構建出來該實體的對象,並且將查詢依據(聯合主鍵)設定進去,然後作為get或load方法的第二個參數傳進去即可。

2) 將主鍵所對應屬性提取出一個類(稱之為主鍵類),並且主鍵類需要實現Serializable介面,重寫equals方法與hashCode方法,原因與上面一樣。

  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.