隨筆-124  評(píng)論-194  文章-0  trackbacks-0
          例如:表示主機(jī)HOST含有多個(gè)磁盤DISK關(guān)系:

          在PD的OOM中雙擊一條關(guān)系連線,設(shè)置Navigate,這樣才會(huì)在各自hbm.xml中生成many-to-one及one-to-many關(guān)系。



          另外,根據(jù)“附文”的效率說(shuō)明還需要設(shè)置:由多方DISK維護(hù)關(guān)系,并且當(dāng)HOST更新時(shí),也要更新DISK。



          生成的HBM.XML如下:
          HOST的:
                <joined-subclass name="Host" table="host" dynamic-update="false" dynamic-insert="false" select-before-update="false" lazy="true" abstract="false"> 
                 <key on-delete="noaction" unique="true">
                   <column name="dev_id" sql-type="int" not-null="true" length="0"/>
                 </key>
                 <array name="nic" optimistic-lock="true">
                  <key on-delete="noaction" unique="true">
                   <column name="dev_id" sql-type="int" not-null="false" length="0"/>
                  </key>
                  <list-index column="IndexColumnB"/>
                  <one-to-many class="eb.nms.db.Nic"/>
                 </array>
                 <set name="disk" outer-join="false" inverse="true" lazy="true" optimistic-lock="true" cascade="save-update">
                  <key on-delete="noaction" unique="true">
                   <column name="dev_id" sql-type="int" not-null="false" length="0"/>
                  </key>
                  <one-to-many class="eb.nms.db.Disk"/>
                 </set>
                </joined-subclass>


          DISK的:
             <class name="Disk" table="disk" mutable="true" lazy="true" abstract="false">
                <id name="diskId">
                   <column name="disk_id" sql-type="int" not-null="true"/>
                   <generator class="native">  
                   </generator>
                </id>
                <property name="diskName" insert="true" update="true" optimistic-lock="true">
                   <column name="disk_name" sql-type="varchar(254)" length="254"/>
                </property>
                <many-to-one name="host" class="Host" outer-join="false" update="true" insert="true">
                 <column name="dev_id" sql-type="int" not-null="false" length="0"/>
                </many-to-one>
             </class>


          附文:
           

          Hibernate Gossip: 雙向關(guān)聯(lián)(inverse 的意義)

          多對(duì)一 一對(duì)多 中都是單向關(guān)聯(lián),也就是其中一方關(guān)聯(lián)到另一方,而另一方不知道自己被關(guān)聯(lián)。

          如果讓雙方都意識(shí)到另一方的存在,這就形成了雙向關(guān)聯(lián),在多對(duì)一、一對(duì)多的例子可以改寫一下,重新設(shè)計(jì)User類別如下:

          • User.java

          package onlyfun.caterpillar;

          public class User {
              private Integer id;
              private String name;
              private Room room;
           
              public User() {}

              public Integer getId() {
                  return id;
              }

              public void setId(Integer id) {
                  this.id = id;
              }

              public String getName() {
                  return name;
              }

              public void setName(String name) {
                  this.name = name;
              }

              public Room getRoom() {
                  return room;
              }

              public void setRoom(Room room) {
                  this.room = room;
              }
          }


          Room
          類別如下:

          • Room.java

          package onlyfun.caterpillar;

          import java.util.Set;

          public class Room {
              private Integer id;
              private String address;
              private Set users;
           
              public Room() {}
           
              public Integer getId() {
                  return id;
              }

              public void setId(Integer id) {
                  this.id = id;
              }
           
              public String getAddress() {
                  return address;
              }
           
              public void setAddress(String address) {
                  this.address = address;
              }

              public Set getUsers() {
                  return users;
              }

              public void setUsers(Set users) {
                  this.users = users;
              }
           
              public void addUser(User user) {
                  users.add(user);
              }
           
              public void removeUser(User user) {
                  users.remove(user);
              }
          }


          如此,User實(shí)例可參考至Room實(shí)例而維持多對(duì)一關(guān)係,而Room實(shí)例記得User實(shí)例而維持一對(duì)多關(guān)係。

          在映射文件方面,可以如下撰寫:

          • User.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="onlyfun.caterpillar.User" table="user">
                  <id name="id" column="id" type="java.lang.Integer">
                      <generator class="native"/>
                  </id>

                  <property name="name" column="name" type="java.lang.String"/>
           
                  <many-to-one name="room"
                               column="room_id"
                               class="onlyfun.caterpillar.Room"
                               cascade="save-update"
                               outer-join="true"/>
              </class>

          </hibernate-mapping>

           

          • Room.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="onlyfun.caterpillar.Room" table="room">
                  <id name="id" column="id">
                      <generator class="native"/>
                  </id>

                  <property name="address"
                            column="address"
                            type="java.lang.String"/>
           
                  <set name="users" table="user" cascade="save-update">
                      <key column="room_id"/>
                      <one-to-many class="onlyfun.caterpillar.User"/>
                  </set>
              </class>

          </hibernate-mapping>


          映射文件雙方都設(shè)定了cascadesave-update,所以您可以用多對(duì)一的方式來(lái)維持關(guān)聯(lián):

          User user1 = new User();
          user1.setName("bush");
                 
          User user2 = new User();
          user2.setName("caterpillar");

          Room room1 = new Room();
          room1.setAddress("NTU-M8-419");

          user1.setRoom(room1);
          user2.setRoom(room1);
                 
          Session session = sessionFactory.openSession();
          Transaction tx = session.beginTransaction();
                 
          session.save(user1);
          session.save(user2);

          tx.commit();
          session.close();


          或是反過(guò)來(lái)由一對(duì)多的方式來(lái)維持關(guān)聯(lián):

          User user1 = new User();
          user1.setName("bush");
                 
          User user2 = new User();
          user2.setName("caterpillar");

          Room room1 = new Room();
          room1.setUsers(new HashSet());
          room1.setAddress("NTU-M8-419");
          room1.addUser(user1);
          room1.addUser(user2);
                 
          Session session = sessionFactory.openSession();
          Transaction tx = session.beginTransaction();
                 
          session.save(room1);

          tx.commit();
          session.close();


          這邊有個(gè)效率議題可以探討,上面的程式片段Hibernate將使用以下的SQL進(jìn)行儲(chǔ)存:

          Hibernate: insert into room (address) values (?)
          Hibernate: insert into user (name, room_id) values (?, ?)
          Hibernate: insert into user (name, room_id) values (?, ?)
          Hibernate: update user set room_id=? where id=?
          Hibernate: update user set room_id=? where id=?


          上面的程式寫法表示關(guān)聯(lián)由Room單方面維持,而主控方也是RoomUser不知道Roomroom_id是多少,所以必須分別儲(chǔ)存Room User之後,再更新userroom_id

          在一對(duì)多、多對(duì)一形成雙向關(guān)聯(lián)的情況下,可以將關(guān)聯(lián)維持的控制權(quán)交給多的一方,這樣會(huì)比較有效率,理由不難理解,就像是在公司中,老闆要記住多個(gè)員工的姓名快,還是每一個(gè)員工都記得老闆的姓名快。

          所以在一對(duì)多、多對(duì)一形成雙向關(guān)聯(lián)的情況下,可以在「一」的一方設(shè)定控制權(quán)反轉(zhuǎn),也就是當(dāng)儲(chǔ)存「一」的一方時(shí),將關(guān)聯(lián)維持的控制權(quán)交給「多」的一方,以上面的例子來(lái)說(shuō),可以設(shè)定Room.hbm.xml如下:

          • Room.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="onlyfun.caterpillar.Room" table="room">
                  <id name="id" column="id">
                      <generator class="native"/>
                  </id>

                  <property name="address"
                            column="address"
                            type="java.lang.String"/>
           
                  <set name="users" table="user" cascade="save-update" inverse="true">
                      <key column="room_id"/>
                      <one-to-many class="onlyfun.caterpillar.User"/>
                  </set>
              </class>

          </hibernate-mapping>


          由於關(guān)聯(lián)的控制權(quán)交給「多」的一方了,所以直接儲(chǔ)存「一」方前,「多」的一方必須意識(shí)到「一」的存在,所以程式片段必須改為如下:

          User user1 = new User();
          user1.setName("bush");
                 
          User user2 = new User();
          user2.setName("caterpillar");

          Room room1 = new Room();
          room1.setUsers(new HashSet());
          room1.setAddress("NTU-M8-419");
          room1.addUser(user1);
          room1.addUser(user2);

          //
          多方必須意識(shí)到單方的存在
          user1.setRoom(room1);

          user2.setRoom(room1);
                 
          Session session = sessionFactory.openSession();
          Transaction tx = session.beginTransaction();
                 
          session.save(room1);

          tx.commit();
          session.close();


          上面的程式片段Hibernate將使用以下的SQL

          Hibernate: insert into room (address) values (?)
          Hibernate: insert into user (name, room_id) values (?, ?)
          Hibernate: insert into user (name, room_id) values (?, ?)


          如果控制權(quán)交給另一方了,而另一方?jīng)]有意識(shí)到對(duì)方的存在的話會(huì)如何?試著將上面的程式片段中user1.setRoom(room1); user2.setRoom(room1);移去,執(zhí)行之後,您會(huì)發(fā)現(xiàn)資料庫(kù)中room_id會(huì)出現(xiàn)null值,這種結(jié)果就好比在 多對(duì)一 中,您沒(méi)有分配給User一個(gè)Room,理所當(dāng)然的,room_id會(huì)出現(xiàn)null

           

          posted on 2007-04-15 17:17 我愛(ài)佳娃 閱讀(6454) 評(píng)論(0)  編輯  收藏 所屬分類: Hibernate
          主站蜘蛛池模板: 宝山区| 定南县| 清流县| 芮城县| 哈巴河县| 桦甸市| 策勒县| 建昌县| 夏津县| 合江县| 普定县| 英吉沙县| 乾安县| 杭州市| 渝北区| 常宁市| 北流市| 洪江市| 治县。| 射阳县| 保德县| 和田市| 万载县| 温宿县| 肥西县| 宕昌县| 安丘市| 泾源县| 甘孜县| 大同市| 武冈市| 大姚县| 辽源市| 固镇县| 吉水县| 崇阳县| 萨嘎县| 江达县| 阿瓦提县| 通辽市| 扬中市|