例如:表示主机HOST含有多个磁盘DISK关系:
在PD的OOM中双击一条关系连线,设置Navigate,这样才会在各自hbm.xml中生成many-to-one及one-to-many关系。

另外,根据“附文”的效率说明还需要设置:由多方DISK维护关系,并且当HOST更新时,也要更新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>
附文: 
    
        
            | 在 多對一 、一對多 中都是單向關聯,也就是其中一方關聯到另一方,而另一方不知道自己被關聯。
 如果讓雙方都意識到另一方的存在,這就形成了雙向關聯,在多對一、一對多的例子可以改寫一下,重新設計User類別如下:
 
            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類別如下:
 
            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實例可參考至Room實例而維持多對一關係,而Room實例記得User實例而維持一對多關係。
 
 在映射文件方面,可以如下撰寫:
 
            <?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>
   
            <?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>
 映射文件雙方都設定了cascade為save-update,所以您可以用多對一的方式來維持關聯:
 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();
 或是反過來由一對多的方式來維持關聯:
 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();
 這邊有個效率議題可以探討,上面的程式片段Hibernate將使用以下的SQL進行儲存:
 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=?
 上面的程式寫法表示關聯由Room單方面維持,而主控方也是Room,User不知道Room的room_id是多少,所以必須分別儲存Room與 User之後,再更新user的room_id。
 
 在一對多、多對一形成雙向關聯的情況下,可以將關聯維持的控制權交給多的一方,這樣會比較有效率,理由不難理解,就像是在公司中,老闆要記住多個員工的姓名快,還是每一個員工都記得老闆的姓名快。
 
 所以在一對多、多對一形成雙向關聯的情況下,可以在「一」的一方設定控制權反轉,也就是當儲存「一」的一方時,將關聯維持的控制權交給「多」的一方,以上面的例子來說,可以設定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>
 由於關聯的控制權交給「多」的一方了,所以直接儲存「一」方前,「多」的一方必須意識到「一」的存在,所以程式片段必須改為如下:
 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);
 
 // 多方必須意識到單方的存在
 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 (?, ?)
 如果控制權交給另一方了,而另一方沒有意識到對方的存在的話會如何?試著將上面的程式片段中user1.setRoom(room1);與 user2.setRoom(room1);移去,執行之後,您會發現資料庫中room_id會出現null值,這種結果就好比在 多對一 中,您沒有分配給User一個Room,理所當然的,room_id會出現null。
 | 
    
 
	posted on 2007-04-15 17:17 
我爱佳娃 阅读(6469) 
评论(0)  编辑  收藏  所属分类: 
Hibernate