入門 22 - 一對一實體映射2004-11-14 11:15:35
假設我們之前範例的User與Room是一對一的關係, User.java package onlyfun.caterpillar; public class User { private long id; private String name; private Room room; public long getId() { return id; } public void setId(long 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.java package onlyfun.caterpillar; public class Room { private long id; private String address; private User user; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } 要映射User與Room的一對一關係,我們可以有兩種方式,一種是透過外鍵參考,在之前的多對一的例子中即使外鍵參考的例子,我們現在限制多對一為一對一,只要在User.hbm.xml中的<many-to-one>上加上unique="true",表示限制一個User有一獨有的 Room: User.hbm.xml <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN""http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="onlyfun.caterpillar.User" table="USER"> <id name="id" column="USER_ID" unsaved-value="0"> <generator class="increment"/> </id> <property name="name"> <column name="NAME" length="16" not-null="true"/> </property> <many-to-one name="room" column="ROOM_ID" class="onlyfun.caterpillar.Room" cascade="all" unique="true"/> </class> </hibernate-mapping> 這就完成了單向的一對一映射,我們可以在Room.hbm.xml上加入參考回User的設定,使其成為雙向的一對一映射,如下: Room.hbm.xml <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN""http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="onlyfun.caterpillar.Room" table="ROOM"> <id name="id" column="ROOM_ID" unsaved-value="0"> <generator class="increment"/> </id> <property name="address" type="string"/> <one-to-one name="user" class="onlyfun.caterpillar.User" property-ref="room"/> </class> </hibernate-mapping> 在<one-to-one>的設定中,我們告訴Hibernate,Room返向參考回User的room屬性。 使用以下的程式來測試資料的儲存: HibernateTest.java import onlyfun.caterpillar.*; import net.sf.hibernate.*; import net.sf.hibernate.cfg.*; public class HibernateTest { public static void main(String[] args) throws HibernateException { SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); Room room = new Room(); room.setAddress("NTU-M8-419"); User user1 = new User(); user1.setName("bush"); user1.setRoom(room); room.setUser(user1); Session session = sessionFactory.openSession(); Transaction tx= session.beginTransaction(); session.save(user1); tx.commit(); session.close(); sessionFactory.close(); } } 資料表的實際例子,與多對一映射時相同,只不過現在一個User只能對應一個Room。 另一個映射一對一的方式是使用主鍵關聯,限制兩個資料表的主鍵使用相同的值,如此一個User與Room就是一對一關係,在User.hbm.xml這邊,只要使用<one-to-one>設定關聯即可: User.hbm.xml <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN""http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="onlyfun.caterpillar.User" table="USER"> <id name="id" column="USER_ID" unsaved-value="0"> <generator class="increment"/> </id> <property name="name"> <column name="NAME" length="16" not-null="true"/> </property> <one-to-one name="room" class="onlyfun.caterpillar.Room" cascade="all"/> </class> 在Room.hbm.xml這邊,必須限制其主鍵與User的主鍵相同,而在屬性上,使用constrained="true"告訴Hibernate參考至User的主鍵: Room.hbm.xml <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN""http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="onlyfun.caterpillar.Room" table="ROOM"> <id name="id" column="ROOM_ID" unsaved-value="0"> <generator class="foreign"> <param name="property">user</param> </generator> </id> <property name="address" type="string"/> <one-to-one name="user" class="onlyfun.caterpillar.User" constrained="true"/> </class> </hibernate-mapping> 只要改變映射文件即可,程式的部份無需修改,資料庫中的實際儲存例子如下: mysql> select * from USER; +---------+-------------+ | USER_ID | NAME | +---------+-------------+ | 1 | bush | | 2 | caterpillar | +---------+-------------+ 2 rows in set (0.00 sec) mysql> select * from ROOM; +---------+------------+ | ROOM_ID | address | +---------+------------+ | 1 | NTU-M8-419 | | 2 | NTU-M8-420 | +---------+------------+ 2 rows in set (0.00 sec) |
|
|