一對一關聯在資料庫層面主要有兩種模式:**唯一外鍵** 與 **主鍵共享**。Hibernate 透過不同的映射配置支援兩者。

CREATE TABLE user (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL DEFAULT '',
room_id INT(11)
);
CREATE TABLE room (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
address VARCHAR(100) NOT NULL DEFAULT ''
);
User 表持有 Room 的外鍵 room_id,並加上 UNIQUE 約束確保一對一。
User.hbm.xml(關係擁有端):
<many-to-one name="room" column="room_id"
class="com.hb3.pack_02.model.Room"
cascade="all" outer-join="true" unique="true"/>
unique="true":產生 DDL 時加上唯一約束,語義上變成一對一。outer-join="true":查詢時使用 LEFT OUTER JOIN 一次撈回關聯物件。Room.hbm.xml(被參考端):
<one-to-one name="user"
class="com.hb3.pack_02.model.User"
property-ref="room"/>
property-ref="room":指向 User 端的屬性名,完成雙向導航。
CREATE TABLE user (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL DEFAULT ''
);
CREATE TABLE room (
id INT(11) NOT NULL PRIMARY KEY, -- 非自增,與 User.id 同值
address VARCHAR(100) NOT NULL DEFAULT ''
);
Room 表的主鍵同時也是指向 User 的外鍵,**主鍵值完全同步**。
User.hbm.xml(主控端):
<one-to-one name="room"
class="com.hb3.pack_18.model.Room"
cascade="all"/>
Room.hbm.xml(從屬端):
<id name="id" column="id">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<one-to-one name="user"
class="com.hb3.pack_18.model.User"
constrained="true"/>
generator class="foreign":主鍵值由關聯的 User 物件決定。constrained="true":產生 DDL 時加上外鍵約束,確保 Room.id 必須存在於 User.id 中。User user = new User(); user.setName("shenbin");
Room room = new Room(); room.setAddress("NTU-M8-419");
// 模式二必須雙向 set,否則 foreign generator 無法取得主鍵值
user.setRoom(room);
room.setUser(user);
session.save(user); // cascade="all" 會自動存 room
| 維度 | 唯一外鍵 | 主鍵共享 |
|---|---|---|
| 資料表結構 | 獨立主鍵,外鍵+唯一索引 | 共享主鍵,強耦合 |
| 彈性 | 可為 null,支援延遲載入 | 不可為 null,通常需急切載入 |
| 適用場景 | 大多數業務場景 | 擴充表、垂直分表、強生命週期綁定 |
實務上**唯一外鍵模式較常用**,彈性較高;主鍵共享適合「實體拆分」場景。