例如:表示主機(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>
附文:
在 多對(duì)一 、一對(duì)多 中都是單向關(guān)聯(lián),也就是其中一方關(guān)聯(lián)到另一方,而另一方不知道自己被關(guān)聯(lián)。
如果讓雙方都意識(shí)到另一方的存在,這就形成了雙向關(guān)聯(lián),在多對(duì)一、一對(duì)多的例子可以改寫一下,重新設(shè)計(jì)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實(shí)例可參考至Room實(shí)例而維持多對(duì)一關(guān)係,而Room實(shí)例記得User實(shí)例而維持一對(duì)多關(guān)係。
在映射文件方面,可以如下撰寫:
<?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>
映射文件雙方都設(shè)定了cascade為save-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單方面維持,而主控方也是Room,User不知道Room的room_id是多少,所以必須分別儲(chǔ)存Room與 User之後,再更新user的room_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如下:
<?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