一個實體簡單的說就是在資料庫中擁有一個表格的物件,並擁有自已的資料庫識別(database identity),之前介紹的Component物件並不是實體,它沒有自已的資料庫識別,具體的話,它沒有id屬性,Hibernate並不會賦予它id值。
實體與實體之間的關係有:一對一、多對一、一對多、多對多。其中多對一算是最常見的實體關係,舉個簡單的例子,假設您在撰寫一個宿舍管理系統,一般來說,房客與房間之間的關係就是一種多對一的關係,因為一間房間可以分配給多個人(學生宿舍啦,一般應該都是二到八個人不等吧!看學校的環境了)。
用程式來表示的話,首先看看Room類別的撰寫,我們只簡單的設定位址屬性於其中:
Room.java
package onlyfun.caterpillar; public class Room { private long id; private String address; 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; } }
注意這個類別與Component物件不同的是,它擁有id屬性,在儲存至資料庫,Hibernate會賦予值給它;房客的話我們設計一個User類別:
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; } }
在Java中,一個Room物件可以被多個User物件參考,也就是說User對Room的關係是多對一的關係,我們也可以反過來設計Room對 User的關係,將其設計為一對多,這在下一個主題中討論,現階段我們先關注多對一的映射,我們的Room映射文件Room.hbm.xml很簡單,如下:
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"> <generator class="increment"/> </id> <property name="address" type="string"/> </class> </hibernate-mapping>
再來是User.hbm.xml的撰寫,我們使用<many-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"> <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"/> </class> </hibernate-mapping>
與User對應的USER表格是透過ROOM_ID的值參考至ROOM表格,當然,最重要的別忘了在hibernate.cfg.xml中指定映射文件的位置與名稱:
hibernate.cfg.xml
<?xml version='1.0' encoding='big5'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"> <hibernate-configuration> <session-factory> ...... <!-- 物件與資料庫表格映射文件 --> <mapping resource="Room.hbm.xml"/> <mapping resource="User.hbm.xml"/> </session-factory> </hibernate-configuration>
我們用下面這個程式簡單的測試一下儲存的結果:
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 room1 = new Room(); room1.setAddress("NTU-M8-419"); Room room2 = new Room(); room2.setAddress("NTU-G3-302"); User user1 = new User(); user1.setName("bush"); user1.setRoom(room1); User user2 = new User(); user2.setName("caterpillar"); user2.setRoom(room1); User user3 = new User(); user3.setName("momor"); user3.setRoom(room2); Session session = sessionFactory.openSession(); Transaction tx= session.beginTransaction(); session.save(room1); session.save(room2); session.save(user1); session.save(user2); session.save(user3); tx.commit(); session.close(); sessionFactory.close(); } }
直接來看看儲存在資料庫中是什麼樣子:
mysql> select * from USER; +---------+-------------+---------+ | USER_ID | NAME | ROOM_ID | +---------+-------------+---------+ | 1 | bush | 1 | | 2 | caterpillar | 1 | | 3 | momor | 2 | +---------+-------------+---------+ 3 rows in set (0.00 sec) mysql> select * from ROOM; +---------+------------+ | ROOM_ID | address | +---------+------------+ | 1 | NTU-M8-419 | | 2 | NTU-G3-302 | +---------+------------+ 2 rows in set (0.00 sec)