隨筆-57  評論-202  文章-17  trackbacks-0
                Hibernate中的表的關聯有一對一,一對多和多對多三種關聯方式,在這篇筆記和接下來的筆記中,我將用我自己的實際例子來說明如何具體實施。
                我使用的Hibernate版本是2.1.8,在Hibernate的網站2.1.6版本的中文文檔中有關一對一的關聯有下面一段表述:

          5.1.11. 一對一
          持久化對象之間一對一的關聯關系是通過one-to-one元素定義的。 

          <one-to-one
                  
          name="propertyName"                                (1)
                  class
          ="ClassName"                                  (2)
                  cascade
          ="all|none|save-update|delete"              (3)
                  constrained
          ="true|false"                           (4)
                  outer-join
          ="true|false|auto"                       (5)
                  property-ref
          ="propertyNameFromAssociatedClass"     (6)
                  access
          ="field|property|ClassName"                  (7)
                  
          />
          (1) name: 屬性的名字。 
           
          (2) class (可選 - 默認是通過反射得到的屬性類型):被關聯的類的名字。 
           
          (3) cascade(級聯) (可選) 表明操作是否從父對象級聯到被關聯的對象。 
           
          (4) constrained(約束) (可選) 表明該類對應的表對應的數據庫表,和被關聯的對象所對應的數據庫表之間,通過一個外鍵引用對主鍵進行約束。這個選項影響save()和delete()在級聯執行時的先后順序(也在schema export tool中被使用)。 
           
          (5) outer-join(外連接) (可選 - 默認為 自動): 當設置hibernate.use_outer_join的時候,對這個關聯允許外連接抓取。 
           
          (6) property-ref: (可選) 指定關聯類的一個屬性,這個屬性將會和本外鍵相對應。如果沒有指定,會使用對方關聯類的主鍵。 
           
          (7) access (可選 - 默認是 property): Hibernate用來訪問屬性的策略。 
           

          有兩種不同的一對一關聯: 

          主鍵關聯 

          惟一外鍵關聯 

          主鍵關聯不需要額外的表字段;兩行是通過這種一對一關系相關聯的,那么這兩行就共享同樣的主關鍵字值。所以如果你希望兩個對象通過主鍵一對一關聯,你必須確認它們被賦予同樣的標識值! 

          比如說,對下面的Employee和Person進行主鍵一對一關聯: 

          <one-to-one name="person" class="Person"/>
          <one-to-one name="employee" class="Employee" constrained="true"/>
          現在我們必須確保PERSON和EMPLOYEE中相關的字段是相等的。我們使用一個特別的稱為foreign的Hibernate標識符生成器策略: 

          <class name="person" table="PERSON">
              
          <id name="id" column="PERSON_ID">
                  
          <generator class="foreign">
                      
          <param name="property">employee</param>
                  
          </generator>
              
          </id>
              
              
          <one-to-one name="employee"
                  class
          ="Employee"
                  constrained
          ="true"/>
          </class>
          一個剛剛保存的Person實例被賦予和該Person的employee屬性所指向的Employee實例同樣的關鍵字值。 

          另一種方式是一個外鍵和一個惟一關鍵字對應,上面的Employee和Person的例子,如果使這種關聯方式,應該表達成: 

          <many-to-one name="person" class="Person" column="PERSON_ID" unique="true"/>
          如果在Person的映射加入下面幾句,這種關聯就是雙向的: 

          <one-to-one name"employee" class="Employee" property-ref="person"/>
                
                下面是我的一個一對一主鍵關聯的例子,使用的數據庫是MySQL 4.1.11:
                我有兩個表:UserBasic和UserInfo,UserBasic記錄的是用戶的基本注冊信息,UserInfo表記錄的是用戶的詳細信息。表的結構如下:

           1CREATE TABLE IF NOT EXISTS UserBasic
           2(
           3   Guid                           INT                            NOT NULL AUTO_INCREMENT,
           4   Account                        VARCHAR(64)                    NOT NULL,
           5   Password                       VARCHAR(16)                    NOT NULL,
           6   Email                          VARCHAR(128)                   NOT NULL,
           7   PRIMARY KEY (Guid)
           8) TYPE=InnoDB;
           9
          10CREATE TABLE IF NOT EXISTS UserInfo
          11(
          12   Guid                           INT                            NOT NULL,
          13   Username                       VARCHAR(128),
          14   Gender                         CHAR(1),
          15   Birthday                       DATETIME,
          16   PRIMARY KEY (Guid)
          17) TYPE=InnoDB;
          18
          19ALTER TABLE UserInfo ADD CONSTRAINT UserInfoRFUserBasic FOREIGN KEY (Guid) 
          20   REFERENCES UserBasic (Guid) ON DELETE CASCADE ON UPDATE RESTRICT;

                UserInfo的主鍵值和UserBasic的主鍵值是一樣的,兩個表是單向的一對一關系。UserBasic為主控方,UserInfo是被動方。
                用Middlegen生成的UserBasic.hbm.xml文件,修改后的內容如下:

            1<?xml version="1.0"?>
            2<!DOCTYPE hibernate-mapping PUBLIC
            3    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
            4    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
            5    
            6<hibernate-mapping>
            7<!-- 
            8    Created by the Middlegen Hibernate plugin 2.1
            9
           10    http://boss.bekk.no/boss/middlegen/
           11    http://www.hibernate.org/
           12-->
           13
           14<class 
           15    name="com.xxx.hibernate.UserBasic" 
           16    table="UserBasic"
           17    dynamic-update="true"
           18    dynamic-insert="true"
           19>
           20    <meta attribute="class-description" inherit="false">
           21       @hibernate.class
           22        table="UserBasic"
           23        dynamic-update="true"
           24        dynamic-insert="true"
           25    </meta>
           26
           27    <id
           28        name="guid"
           29        type="int"
           30        column="Guid"
           31    >
           32        <meta attribute="field-description">
           33           @hibernate.id
           34            generator-class="native"
           35            type="int"
           36            column="Guid"
           37
           38
           39        </meta>
           40        <generator class="native" />
           41    </id>
           42
           43    <property
           44        name="account"
           45        type="java.lang.String"
           46        column="Account"
           47        not-null="true"
           48        length="64"
           49    >
           50        <meta attribute="field-description">
           51           @hibernate.property
           52            column="Account"
           53            length="64"
           54            not-null="true"
           55        </meta>    
           56    </property>
           57    <property
           58        name="password"
           59        type="java.lang.String"
           60        column="Password"
           61        not-null="true"
           62        length="16"
           63    >
           64        <meta attribute="field-description">
           65           @hibernate.property
           66            column="Password"
           67            length="16"
           68            not-null="true"
           69        </meta>    
           70    </property>
           71    <property
           72        name="email"
           73        type="java.lang.String"
           74        column="Email"
           75        not-null="true"
           76        length="128"
           77    >
           78        <meta attribute="field-description">
           79           @hibernate.property
           80            column="Email"
           81            length="128"
           82            not-null="true"
           83        </meta>    
           84    </property>
           85
           86    <!-- Associations -->
           87  
           88    <!-- bi-directional one-to-one association to UserInfo -->
           89    <one-to-one
           90        name="userInfo"
           91        class="com.xxx.hibernate.UserInfo"
           92        cascade="save-update"
           93    >
           94        <meta attribute="field-description">
           95           @hibernate.one-to-one
           96               class="com.xxx.hibernate.UserInfo"
           97            cascade="save-update"
           98        </meta>
           99    </one-to-one>
          100
          101</class>
          102</hibernate-mapping>

                由于在建立外鍵的時候就聲明了ON DELETE CASCADE,所以在xml的配置文件中第97行聲明為save-update。如果聲明為all,那么在刪除UserBasic表的數據時,會無謂的多出一條刪除UserInfo的delete語句出來。
                UserInfo.hbm.xml文件的內容如下:

           1<?xml version="1.0"?>
           2<!DOCTYPE hibernate-mapping PUBLIC
           3    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
           4    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
           5    
           6<hibernate-mapping>
           7<!-- 
           8    Created by the Middlegen Hibernate plugin 2.1
           9
          10    http://boss.bekk.no/boss/middlegen/
          11    http://www.hibernate.org/
          12-->
          13
          14<class 
          15    name="com.xxx.hibernate.UserInfo" 
          16    table="UserInfo"
          17    dynamic-update="true"
          18    dynamic-insert="true"
          19>
          20    <meta attribute="class-description" inherit="false">
          21       @hibernate.class
          22        table="UserInfo"
          23        dynamic-update="true"
          24        dynamic-insert="true"
          25    </meta>
          26
          27    <id
          28        name="guid"
          29        type="int"
          30        column="Guid"
          31    >
          32        <meta attribute="field-description">
          33           @hibernate.id
          34            generator-class="foreign"
          35            type="int"
          36            column="Guid"
          37
          38
          39        </meta>
          40        <generator class="foreign">
          41            <param name="property">userBasic</param>
          42        </generator>
          43    </id>
          44
          45    <property
          46        name="username"
          47        type="java.lang.String"
          48        column="Username"
          49        length="128"
          50    >
          51        <meta attribute="field-description">
          52           @hibernate.property
          53            column="Username"
          54            length="128"
          55        </meta>    
          56    </property>
          57    <property
          58        name="gender"
          59        type="java.lang.String"
          60        column="Gender"
          61        length="1"
          62    >
          63        <meta attribute="field-description">
          64           @hibernate.property
          65            column="Gender"
          66            length="1"
          67        </meta>    
          68    </property>
          69    <property
          70        name="birthday"
          71        type="java.sql.Date"
          72        column="Birthday"
          73        length="19"
          74    >
          75        <meta attribute="field-description">
          76           @hibernate.property
          77            column="Birthday"
          78            length="19"
          79        </meta>    
          80    </property>
          81
          82    <!-- Associations -->
          83  
          84    <!-- bi-directional one-to-one association to UserBasic -->
          85    <one-to-one
          86        name="userBasic"
          87        class="com.xxx.hibernate.UserBasic"
          88        constrained="true"
          89    >
          90        <meta attribute="field-description">
          91           @hibernate.one-to-one
          92            class="com.xxx.hibernate.UserBasic"
          93            constrained="true"
          94        </meta>    
          95    </one-to-one>
          96    
          97</class>
          98</hibernate-mapping>

                用hbm2java生成對應的對應的Java類:hbm2java *.xml --output=xxx。
                Hibernate的配置文件hibernate.cfg.xml內容如下:

           1<?xml version="1.0" encoding="utf-8"?>
           2<!DOCTYPE hibernate-configuration
           3    PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
           4    "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
           5
           6<hibernate-configuration>
           7    <session-factory>
           8
           9        <!-- local connection properties -->
          10        <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1/xxx?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true</property>
          11        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
          12        <property name="hibernate.connection.username">root</property>
          13        <property name="hibernate.connection.password">123456</property>
          14        <!-- property name="hibernate.connection.pool_size"></property -->
          15
          16        <!-- dialect for MySQL -->
          17        <property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
          18
          19        <property name="hibernate.show_sql">true</property>
          20        <property name="hibernate.use_outer_join">true</property>
          21        <property name="hibernate.transaction.factory_class">net.sf.hibernate.transaction.JDBCTransactionFactory</property>
          22        
          23        <mapping resource="com/xxx/hibernate/UserBasic.hbm.xml"/>
          24        <mapping resource="com/xxx/hibernate/UserInfo.hbm.xml"/>
          25
          26    </session-factory>
          27</hibernate-configuration>

                JUnit的測試用例程序片斷如下:

           1    public void testInsertUser() throws Exception {
           2        UserBasic user = new UserBasic();
           3        user.setAccount("test");
           4        user.setPassword("123456");
           5        user.setEmail("georgehill@21cn.com");
           6        
           7        UserInfo info = new UserInfo();
           8        info.setUsername("George Hill");
           9        info.setGender("M");
          10        info.setBirthday(new Date());
          11        
          12        user.setUserInfo(info);
          13        info.setUserBasic(user);
          14        
          15        Transaction tx = session.beginTransaction();
          16        session.save(user);
          17        tx.commit();
          18    }

                運行測試程序,可以看到輸出了兩條insert語句。
          posted on 2005-05-14 15:02 小米 閱讀(4051) 評論(2)  編輯  收藏 所屬分類: Hibernate

          評論:
          # re: Hibernate的一對一關聯實例 2014-10-16 16:03 | vds
          好樣的  回復  更多評論
            
          # re: Hibernate的一對一關聯實例 2016-06-17 15:32 | 33
          根據寫了報錯了是怎么回事  回復  更多評論
            
          主站蜘蛛池模板: 郧西县| 湟中县| 东海县| 青神县| 安康市| 万宁市| 儋州市| 旌德县| 五家渠市| 黄龙县| 永济市| 岳阳市| 石泉县| 博白县| 凤山市| 临夏县| 融水| 枣强县| 松桃| 加查县| 茂名市| 沾益县| 铜鼓县| 巴楚县| 获嘉县| 绥宁县| 宽城| 德庆县| 包头市| 德昌县| 诸暨市| 曲水县| 呼玛县| 富平县| 辽宁省| 茶陵县| 惠水县| 平武县| 玉门市| 晋宁县| 三原县|