在 多對一 中,User對Room是多對一的關係,User實例維護著對Room實例的參考,如果將這個關係反過來,由Room實例維護對多個User實例的資料, 就是一對多的關係。
具體來說,可以設計User類別如下:
- User.java
package onlyfun.caterpillar;
public class User {
private Long id;
private String name;
public User() {}
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;
}
}
而在Room類別中,使用Set來記錄多個User:
- Room.java
package onlyfun.caterpillar;
import java.util.Set;
public class Room {
private Long id;
private String address;
private Set users;
public Room() {}
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 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);
}
}
這種方式即所謂單向一對多關係,也就是Room實例知道User實例的存在,而User實例則沒有意識到Room實例。
(在 多對一 中,則是單向多對一關係,即User知道Room的存在,但Room不知道User的存在。)
在映射文件上,先來看看User.hbm.xml:
- 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">
<generator class="native"/>
</id>
<property name="name" column="name"/>
</class>
</hibernate-mapping>
在單向關係中,被參考的對象其映射文件就如單一實體一樣的配置,接下來看看Room.hbm.xml,使用<one-to- many>標籤配置一對多:
- 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="all">
<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");
User user3 = new User();
user3.setName("momor");
Room room1 = new Room();
room1.setUsers(new HashSet());
room1.setAddress("NTU-M8-419");
room1.addUser(user1);
room1.addUser(user2);
Room room2 = new Room();
room2.setUsers(new HashSet());
room2.setAddress("NTU-G3-302");
room2.addUser(user3);
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(room1); // cascade 操作
session.save(room2);
tx.commit();
session.close();
user1.setName("bush");
User user2 = new User();
user2.setName("caterpillar");
User user3 = new User();
user3.setName("momor");
Room room1 = new Room();
room1.setUsers(new HashSet());
room1.setAddress("NTU-M8-419");
room1.addUser(user1);
room1.addUser(user2);
Room room2 = new Room();
room2.setUsers(new HashSet());
room2.setAddress("NTU-G3-302");
room2.addUser(user3);
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(room1); // cascade 操作
session.save(room2);
tx.commit();
session.close();
資料庫中將儲存以下的表格:
mysql> select *
from user;
+----+--------------+-----------+
| id | name | room_id |
+----+-------------+------------+
| 1 | bush | 1 |
| 2 | caterpillar | 1 |
| 3 | momor | 2 |
+----+-------------+------------+
3 rows in set (0.01 sec)
mysql> select * from room;
+----+------------------+
| id | address |
+----+------------------+
| 1 | NTU-M8-419 |
| 2 | NTU-G3-302 |
+----+------------------+
2 rows in set (0.00 sec)
+----+--------------+-----------+
| id | name | room_id |
+----+-------------+------------+
| 1 | bush | 1 |
| 2 | caterpillar | 1 |
| 3 | momor | 2 |
+----+-------------+------------+
3 rows in set (0.01 sec)
mysql> select * from room;
+----+------------------+
| id | address |
+----+------------------+
| 1 | NTU-M8-419 |
| 2 | NTU-G3-302 |
+----+------------------+
2 rows in set (0.00 sec)
關於一對多還有效能方面的一些議題,可以參考 雙向關聯(inverse 的意義)。