Hibernate映射--基本類映射和對象關系映射(轉)


原文地址:http://blog.csdn.net/lovesummerforever/article/details/20901011   尊重原創,請訪問原網址

 

回想一些我們在沒有學習ssh的時候,我們建立數據庫的表時,首先是數據庫建模E-R圖,然后再通過實體模型來建立關系模型,再建立相應的表。實體間存在三種關系,一對一,一對多(或者說多對一),多對多。而如今我們要根據類來映射相應的表,那只能是通過類與類之間的關系加上映射文件來映射數據庫的表。我們學習UML建模,類與類之間存在五種關系,繼承,實現,關聯,依賴,聚合/組合,在hibernate中實體類之間的關系也是如此,對於不同的關系對應的代碼實現我們已經很熟悉了,所以對於實體類是復習的知識。

Hibernate的本質就是對象關系映射(ObjectRelational Mapping),ORM實現了將對象數據保存到數據庫中,以前我們對關系表進行操作,執行增刪改查等任務,現在我們不再對關系表進行操作,而是直接對對象操作。hibernate中的ORM映射文件通常以.hbm.xml作為后綴。使用這個映射文件不僅易讀,而且可以手工修改,也可以通過一些工具來生成映射文檔。下面將對hibernate中的映射進行介紹。

Hibernate映射分類,如下圖所示。

 

1 基本類映射

根據實體類創建相應的表,這種簡單的關系為hibernate基本映射。

User1實體類代碼如下:

 

[java]  view plain  copy
 
  print ?
  1. //user實體。  
  2. public classUser1 {  
  3.    //用戶編號。  
  4.    private String id;  
  5.     
  6.    //名字。  
  7.    private String name;  
  8.     
  9.    //密碼。  
  10.    private String password;  
  11.     
  12.    //創建日期。  
  13.    private Date createTime;  
  14.     
  15.    //失效時間。  
  16.     private Date expireTime;  
  17.    
  18.    public String getId() {  
  19.       return id;  
  20.    }  
  21.    
  22. // publicvoid setId(String id) {  
  23. //    this.id= id;  
  24. // }  
  25.    
  26.    public String getName() {  
  27.       return name;  
  28.    }  
  29.    
  30.    public void setName(String name) {  
  31.       this.name = name;  
  32.    }  
  33.    
  34.    public String getPassword() {  
  35.       return password;  
  36.    }  
  37.    
  38.    public void setPassword(Stringpassword) {  
  39.       this.password = password;  
  40.    }  
  41.    
  42.    public Date getCreateTime() {  
  43.       return createTime;  
  44.    }  
  45.    
  46.    public void setCreateTime(DatecreateTime) {  
  47.       this.createTime = createTime;  
  48.    }  
  49.    
  50.    public Date getExpireTime() {  
  51.       return expireTime;  
  52.    }  
  53.    
  54.    public void setExpireTime(DateexpireTime) {  
  55.       this.expireTime = expireTime;  
  56.    }  
  57.  }  

 

User1.hbm.xml映射文件如下所示:

 

[html]  view plain  copy
 
  print ?
  1. <hibernate-mapping package="com.bjpowernode.hibernate">  
  2.    
  3.    <class name="User1"  table="t_user1">  
  4.       <id name="id"column="user_id" length="32"access="field">  
  5.          <generator class="uuid" />  
  6.       </id>  
  7.       <!-- 設置主鍵不能重復和不能為空的屬性. -->  
  8.       <property name="name" length="30"unique="true" not-null="true"/>  
  9.       <property name="password"/>  
  10.       <property name="createTime" type="date" column="create_time"/>  
  11.       <property name="expireTime"/>  
  12.    </class>  
  13. </hibernate-mapping>  

 

 

通過User1.hbm.xml映射文件將User1對象轉換為關系數據庫中的表t_user1。

轉換出的結果如下所示:

 

 

2 對象關系映射

 

    2.1 多對一關聯映射(單向)

 

例如用戶和組的關系就是多對一的關系,多個用戶對應一個組。

 

 

將實體映射成表,將對應的實體映射成表。對應的屬性映射成表字段。

多對一關聯映射是在多的一端來維護關聯字段,在我們這個例子中也就是在用戶一端來維護關系字段。

User.hbm.xml文件。

 

[html]  view plain  copy
 
  print ?
  1. <hibernate-mapping package="org.hibernate.auction">  
  2.    
  3.    <class name="com.bjpowernode.hibernate.User" table="t_user" >  
  4.       <id name="id">  
  5.          <generator class="native" />  
  6.       </id>  
  7.       <property name="name"/>  
  8.       <many-to-one name="group"  column="groupid"cascade="save-update"></many-to-one>  
  9.    </class>  
  10. </hibernate-mapping>  

 

 

Group.hbm.xml文件。

 

[html]  view plain  copy
 
  print ?
  1. <hibernate-mapping package="org.hibernate.auction">  
  2.    
  3.    <class name="com.bjpowernode.hibernate.Group"  table="t_group">  
  4.       <id name="id">  
  5.          <generator class="native" />  
  6.       </id>  
  7.       <property name="name"/>  
  8.    </class>  
  9. </hibernate-mapping>  

 

 

在這里我們看的代碼就看*.hbm.mlx代碼,因為對於類之間的關聯,在實現時,一個類作為另一個類的私有成員,這一點在學UML建模的時候我們都懂了,在這里主要看的是ORM的M,也就是*.hbm.xml文件。

 

    2.2 一對一關聯映射

 

一對一關聯映射在實際生活中是比較常見的,如人與家庭住址的關系,通過人這個對象可以找到他家庭住址相關的內容。

    2.2.1 一對一映射(單向主鍵關聯)

 

 

 

單向一對一主鍵關聯,靠的是它們的主鍵相等,從Person中能看到IdCard,也就是把t_idCard中的主鍵拿過來當做t_Pseron的主鍵。

Xml文件中:

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.Person"table="t_person" >  
  2.       <id name="id">  
  3.       <!-- 采用foreign生成策略,foreign會取得關聯對象的標識 -->  
  4.          <generator class="foreign" >  
  5.          <!--property指的是關聯對象。  -->  
  6.             <param name="property">idCard</param>  
  7.          </generator>  
  8.       </id>  
  9.       <property name="name"/>  
  10.       <!-- 一對一關聯映射,主鍵關聯.  -->  
  11.       <!--  
  12.       one-to-one標簽指示hibernate如何加載其關聯對象,默認根據主鍵加載.  
  13.       也就是拿到關系字段值,根據對端的主鍵來加載關聯對象.  
  14.       constrained="true",表示當前主鍵(Person的主鍵)還是一個外鍵 .  
  15.       參照了對端的主鍵(IdCard的主鍵),也就是會生成外鍵約束語句.  
  16.       -->  
  17.       <one-to-one name="idCard" constrained="true"/>  
  18.    </class>  

 

 

 

[html]  view plain  copy
 
  print ?
  1. <hibernate-mapping package="org.hibernate.auction">  
  2.    
  3.    <class name="com.bjpowernode.hibernate.IdCard" table="t_idCard" >  
  4.       <id name="id">  
  5.          <generator class="native" />  
  6.       </id>  
  7.       <property name="cardNo"/>  
  8.    </class>  
  9. </hibernate-mapping>  

 

 

一對一的關系是通過one-to-one元素定義的。

 

   2.2.2 一對一映射(雙向主鍵關聯)

 

一對一雙向主鍵關聯與一對一單向主鍵關聯的區別就是,一對一單向主鍵關聯,在person端能看到idCard,而idCard不能看到Person端。而雙向關聯就是在idCard端也能看到person,也就是不但在Person.hbm.xml中加上<one-to-one>標簽,同時在IdCard.hbm.xml文件中加上<one-to-one>標簽。代碼如下所示。

 

[html]  view plain  copy
 
  print ?
  1. <hibernate-mapping package="org.hibernate.auction">  
  2.    
  3.    <class name="com.bjpowernode.hibernate.IdCard" table="t_idCard" >  
  4.       <id name="id">  
  5.          <generator class="native" />  
  6.       </id>  
  7.       <property name="cardNo"/>  
  8.       <one-to-one name="person"/>  
  9.    </class>  
  10. </hibernate-mapping>  

 

 

 

 

    2.2.3 一對一映射(單向唯一外鍵關聯)

 

一對一單向唯一外鍵關聯,也就是多對一關聯的特例,把多的一端限制為一,就是一對一唯一外鍵關聯。同多對一一樣,在一端加入另一端的並采用<many-to-one>標簽,通過unique="true",這樣來限制了多的一端為一。

先上代碼。

IdCard.hbm.xml

 

[html]  view plain  copy
 
  print ?
  1. <hibernate-mapping package="org.hibernate.auction">  
  2.    
  3.    <class name="com.bjpowernode.hibernate.IdCard" table="t_idCard" >  
  4.       <id name="id">  
  5.          <generator class="native" />  
  6.       </id>  
  7.       <property name="cardNo"/>  
  8.    </class>  
  9. </hibernate-mapping>  

 

 

Person.hbm.xml

 

[html]  view plain  copy
 
  print ?
  1. <hibernate-mapping package="org.hibernate.auction">  
  2.    
  3.    <class name="com.bjpowernode.hibernate.Person" table="t_person" >  
  4.       <id name="id">  
  5.       <!-- 采用foreign生成策略,foreign會取得關聯對象的標識 -->  
  6.          <generator class="native" />  
  7.        
  8.       </id>  
  9.       <property name="name"/>  
  10.       <many-to-one name="idCard" unique="true"></many-to-one>  
  11.     
  12.    </class>  
  13. </hibernate-mapping>  

 

 

圖如下所示:

 

 

在t_pserson端加上一個外鍵字段idCard,限制idCard的唯一性就是一對一唯一外鍵關聯。

 

    2.2.4 一對一映射(雙向唯一外鍵關聯)

 

一對一唯一外鍵單向關聯我們已經了解了,雙向反過來就是在沒有的一端加上就可以了。

我們的IdCard.hbm.xml中采用<one-to-one>標簽。

 

[html]  view plain  copy
 
  print ?
  1. <hibernate-mapping package="org.hibernate.auction">  
  2.    
  3.    <class name="com.bjpowernode.hibernate.IdCard" table="t_idCard" >  
  4.       <id name="id">  
  5.          <generator class="native" />  
  6.       </id>  
  7.       <property name="cardNo"/>  
  8.       <one-to-one name="person" property-ref="idCard"></one-to-one>  
  9.    </class>  
  10. </hibernate-mapping>  

 

 

而person.hbm.xml同一對一唯一外鍵單向關聯一樣。

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.Person" table="t_person" >  
  2.     <id name="id">  
  3.     <!-- 采用foreign生成策略,foreign會取得關聯對象的標識 -->  
  4.        <generator class="native" />  
  5.      
  6.     </id>  
  7.     <property name="name"/>  
  8.     <many-to-one name="idCard" unique="true"></many-to-one>  
  9.   
  10.  </class>  

 

 

 

 

 

從上述中可以總結出,對於一對一關聯映射,主鍵關聯和唯一外鍵關聯單向和雙向產生出的表結構是一樣的,不同的是在加載的時候不同。也就是一對一雙向關聯和一對一單向關聯的相比,只是改變了一對一關聯映射的加載,而沒有改變存儲。

 

    2.3 一對多關聯映射

 

    2.3.1 一對多關聯映射(單向)

 

上面我們介紹了多對一,我們反過來看一對多不就是多對一嗎?那還用再進行不同的映射嗎?有什么差別嗎?一對多和多對一映射原理是一致的,存儲是相同的,也就是生成的數據庫的表是一樣的,他們之間不同的是維護的關系不同。

他們之間不同點是維護的關系不同

*多對一維護的關系是:多指向一的關系,有了此關系,加載多的時候可以將一加載上來。

*一對多維護的關系是:一指向多的關系,有了此關系,在加載一的時候可以將多加載上來。

 

 

代碼如下所示。

Class.hbm.xml

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.Classes" table="t_Classes" >  
  2.       <id name="id">  
  3.          <generator class="native" />  
  4.       </id>  
  5.       <property name="name"/>  
  6.       <set name="students">  
  7.       <!--  
  8.          <keycolumn="classesid" not-null="true"/> 
  9.       -->  
  10.          <key column="classesid" />  
  11.          <one-to-many class="com.bjpowernode.hibernate.Student"/>  
  12.       </set>  
  13.    </class>  

 

 

Students.hbm.xml

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.Student" table="t_student" >  
  2.      <id name="id">  
  3.         <generator class="native" />  
  4.      </id>  
  5.      <property name="name"/>  
  6.   </class>  

 

  

從班級能看到學生,是班級來維護關系,不是學生來維護關系,學生不知道自己是哪個班,所以在存儲學生的時候,班級的代碼不知道。為了更新學生是哪個班級的要發出很多update語句來告訴學生是哪個班級的。當我們設置classesid not-null=“true”時,則將無法保存數據,解決辦法我們改為雙向關聯映射。

 

    2.3.2 一對多關聯映射(雙向)

 

為了解決一對多單向可能存在的問題,我們采用雙向一對多,每一方都能維護對方。

 

一對多雙向關聯映射方式:

     *在一的一端的集合上采用<key>標簽,在多的一端加入一個外鍵。

     *在多的一端采用<many-to-one>的標簽

!~注意<key>標簽和<many-to-one>標簽加入字段保持一致,否則會產生數據混亂。

代碼如下所示。

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.Classes" table="t_Classes" >  
  2.       <id name="id">  
  3.          <generator class="native" />  
  4.       </id>  
  5.       <property name="name"/>  
  6.       <set name="students" inverse="true">  
  7.       <!--  
  8.          <keycolumn="classesid" not-null="true"/> 
  9.       -->  
  10.          <key column="classesid" />  
  11.          <one-to-many class="com.bjpowernode.hibernate.Student"/>  
  12.       </set>  
  13.    </class>  

 

 

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.Student" table="t_student" >  
  2.       <id name="id">  
  3.          <generator class="native" />  
  4.       </id>  
  5.       <property name="name"/>  
  6.        <many-to-one name="classes"column="classesid"/>  
  7.    </class>  



 

注意:Inverse屬性

1、          Inverse中文意思為相反的,反轉。在hibernate中inverse可以用在一對多和多對多雙向關聯上,inverse默認是false,為false的時候表示本端可以維護關系,如果inverse為true,則本端不能維護關系,會交給另一端維護關系,本端失效,所以在一對多關聯映射我們通常在多的一端維護關系,讓一的一端失效。

2、          Inverse是控制方向上的反轉,只影響存儲。

比較一對多單向和雙向映射,從存儲結構上看沒有什么區別,但是從配置文件上看,一對多雙向比一對多單向,一對多雙向關聯的配置文件中在多的一端的配置文件上存在<many-to-one>相關配置,即保證多對一的映射。

 

 

    2.4 多對多關聯映射

 

    2.4.1 多對多關聯映射(單向)

 

多對多對象關系映射,需要加入一張新表完成基本映射。如下圖所示。

 

代碼。

Role.hbm.xml

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.Role"  table="t_role">  
  2.       <id name="id">  
  3.          <generator class="native" />  
  4.       </id>  
  5.       <property name="name"/>  
  6.        
  7.    </class>  

 

User.hbm.xml

 

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.User" table="t_user" >  
  2.       <id name="id">  
  3.          <generator class="native" />  
  4.       </id>  
  5.       <property name="name"/>  
  6.           
  7.       <set name="roles" table="t_user_role">  
  8.          <key column="user_id"/>  
  9.          <many-to-many class="com.bjpowernode.hibernate.Role"  column="role_id"/>  
  10.       </set>  
  11.    </class>  

 

 

 

    2.4.2 多對多關聯映射(雙向)

 

雙向多對多對象關系映射,是兩端都能將對方加載上來,雙向都需要加上標簽映射。

要注意:

*生成中間表名必須一樣

*生成中間表字段必須一樣

 

代碼如下所示。

Role.hbm.xml

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.Role"  table="t_role">  
  2.      <id name="id">  
  3.         <generator class="native" />  
  4.      </id>  
  5.      <property name="name"/>  
  6.       
  7.      <set name="users"  table="t_user_role">  
  8.         <key column="role_id"/>  
  9.         <many-to-many class="com.bjpowernode.hibernate.User" column="user_id"/>  
  10.      </set>  
  11.   </class>  

 

  .User.hbm.xml

 

[html]  view plain  copy
 
  print ?
  1. <class name="com.bjpowernode.hibernate.User"table="t_user" >  
  2.       <id name="id">  
  3.          <generator class="native" />  
  4.       </id>  
  5.       <property name="name"/>  
  6.           
  7.       <set name="roles" table="t_user_role">  
  8.          <key column="user_id"/>  
  9.          <many-to-many class="com.bjpowernode.hibernate.Role"  column="role_id"/>  
  10.       </set>  
  11.    </class>  



 

區別:單向多對多和雙向多對多存儲結構沒有任何的區別,但他們的映射文件是有區別的,加載過程是不同的。

 

 

        3  關系映射總結

 

綜上所述,可以看出,同一類映射,無論是單向還是雙向,他們的存儲結構是相同的,之所以映射文件不同,是因為加載時不同(在增刪改時)。

無論是多對一、一對多、一對一還是多對一,A對B,A就是主動方,A主動想要了解B的情況,這樣把B設置到A端。而雙向,也就是A對B,A想了解B的信息,而B也想了解A的信息,那就要同時把A設置到B端了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM