首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

NHibernate 一對一關聯映射完整範例:User 與 Profile 雙向關聯

     編輯:關於.NET

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)
);

映射檔案

User.hbm.xml

<?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>

Profile.hbm.xml

<?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"`關閉延遲載入,立即載入關聯 (視效能需求調整)

常見錯誤與解決

  • Foreign key violation:儲存順序錯誤,確保 `session.Save(user)` 而非先存 Profile
  • Duplicate entry:雙向關聯未對齊 (`user.Profile.User != user`),儲存前務必雙向指派
  • IdentifierGenerationException:Profile 使用 `assigned` 生成器而非 `foreign`,導致 Id 未自動賦值

一對一共享主鍵是「強關聯」建模:生命週期完全一致、永不獨立存在。若 Profile 可選擇性存在,改用 `` (一對多唯一) 更彈性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved