NHibernate 映射一對一關聯 (共享主鍵/外鍵關聯) 完整 HBM XML 與程式碼範例,涵蓋雙向導航、級聯儲存、外鍵生成策略。
CREATE TABLE Users (
Id VARCHAR(40) PRIMARY KEY, -- UUID
Name VARCHAR(50), Password VARCHAR(100), ...
);
CREATE TABLE Profiles (
Id VARCHAR(40) PRIMARY KEY, -- 與 User.Id 共享,也是外鍵
UserId VARCHAR(40) UNIQUE, -- 可選,明確外鍵欄位
Bio TEXT, AvatarUrl VARCHAR(200), ...
FOREIGN KEY (Id) REFERENCES Users(Id)
);
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="MyApp.Models" assembly="MyApp">
<class name="User" table="Users" lazy="false">
<id name="Id">
<column name="Id" sql-type="varchar(40)" not-null="true"/>
<generator class="uuid.hex"/>
</id>
<property name="Name" />
<property name="Password" />
<!-- 一對一:共享主鍵,級聯全部操作 -->
<one-to-one name="Profile" class="Profile" cascade="all" />
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="MyApp.Models" assembly="MyApp">
<class name="Profile" table="Profiles" lazy="false">
<id name="Id">
<column name="Id" sql-type="varchar(40)" not-null="true"/>
<!-- 外鍵生成器:從關聯的 User 取得 Id -->
<generator class="foreign">
<param name="property">User</param>
</generator>
</id>
<property name="Bio" />
<property name="AvatarUrl" />
<!-- 反向一對一:constrained="true" 表示外鍵約束 -->
<one-to-one name="User" class="User" constrained="true" />
</class>
</hibernate-mapping>
public class User
{
public virtual string Id { get; set; }
public virtual string Name { get; set; }
public virtual string Password { get; set; }
public virtual Profile Profile { get; set; }
}
public class Profile
{
public virtual string Id { get; set; }
public virtual string Bio { get; set; }
public virtual string AvatarUrl { get; set; }
public virtual User User { get; set; }
}
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
var user = new User
{
Name = "John",
Password = "hash",
Profile = new Profile { Bio = "Developer", AvatarUrl = "/img/john.jpg" }
};
user.Profile.User = user; // 雙向關聯對齊
session.Save(user); // cascade="all" 自動儲存 Profile
tx.Commit();
}
| 映射屬性 | 作用 |
|---|---|
| `generator class="foreign"` | Profile.Id 由關聯的 User.Id 產生,確保共享主鍵 |
| `param name="property"` | 指向反向導航屬性名稱 (`User`) |
| `constrained="true"` | Profile 端宣告外鍵約束,資料庫層面保證一致性 |
| `cascade="all"` | User 儲存/刪除/更新自動級聯至 Profile |
| `lazy="false"` | 關閉延遲載入,立即載入關聯 (視效能需求調整) |
一對一共享主鍵是「強關聯」建模:生命週期完全一致、永不獨立存在。若 Profile 可選擇性存在,改用 `
` (一對多唯一) 更彈性。