天天看點

NHibernate之映射檔案配置說明(轉載2)七、版本(version)(可選)九、property十、多對一(many-to-one)十一、一對一

六、鑒别器

   在"一棵對象繼承樹對應一個表"的政策中,<discriminator>元素是必需的, 它定義了表的鑒别器字段。

鑒别器字段包含标志值,用于告知持久化層應該為某個特定的行建立哪一個子類的執行個體。 如下這些受到限制的類型可以使用: String, Char, Int32,Byte, Short, Boolean , YesNo, TrueFalse。

(1)

column (可選 - 預設為 class) 鑒别器字段的名字

(2)

type (可選 - 預設為 String) 一個NHibernate字段類型的名字。

(3)

force(強制) (可選 - 預設為 false)

"強制"NHibernate指定允許的鑒别器值,即使當取得的所有執行個體都是根類的。

(4)

insert (可選 - 預設為true)

如果你的鑒别器字段也是映射為複合辨別(composite identifier)的一部分, 則需将 這個值設為false。

(5)

formula (可選)

一個SQL表達式,在類型判斷(判斷是父類還是具體子類-譯注)時執行。可用于基于内容的鑒别器。

  鑒别器字段的實際值是根據discriminator-value 和<class> and <subclass>元素中 的discriminator-value屬性得來的。

  force屬性僅僅在這種情況下有用的:表中包含沒有被映射到持久化類的附加辨識器值。

這種情況不會經常遇到。

  使用formula屬性你可以定義一個SQL表達式,用來判斷一個行資料的類型。

  <version>元素是可選的,表明表中包含附帶版本資訊的資料。

這在你準備使用 長事務(long

transactions)的時候特别有用。

  說明:

column (可選 - 預設為屬性名): 指定持有版本号的字段名。

name 持久化類的屬性名。

type (可選 - 預設是 Int32): 版本号的類型。

access (可選 - 預設是 property):

NHibernate用于通路屬性值的政策。

unsaved-value(可選 - 預設是undefined):

用于标明某個執行個體時剛剛被執行個體化的(尚未儲存)版本屬性值, 依靠這個值就可以把這種情況

和已經在先前的session中儲存或裝載的脫管(detached)執行個體區分開來。 (undefined指明應被使用的辨別屬性值。)

(6)

generated(可選 - 預設是 never): 表明此版本屬性值是否實際上是由資料庫生成的。 請參閱 部分的讨論。

版本号必須是以下類型:Int64, Int32, Int16, Ticks,或者 Timestamp, TimeSpan。

  可選的<timestamp>元素指明了表中包含時間戳資料。 這用來作為版本的替代。

時間戳本質上是一種對樂觀鎖定的一種不是特别安全的實作。當然, 有時候應用程式可能在其他方面使用時間戳。

 說明:

column(可選 - 預設為屬性名): 持有時間戳的字段名。

name: 在持久化類中的.NE風格的屬性名, 其.NE類型是 DateTime的。

access (可選 - 預設是 property): NHibernate用于通路屬性值的政策。

unsaved-value (可選 - 預設是null):

用于标明某個執行個體時剛剛被執行個體化的(尚未儲存)版本屬性值, 依靠這個值就可以把這種情況和

已經在先前的session中儲存或裝載的脫管(detached)執行個體區分開來。 (undefined 指明使用辨別屬性值進行這種判斷。)

generated : 指出時間戳值是否實際上是由資料庫生成的.請參閱的讨論。

  注意<timestamp>等價于 <version type="timestamp">。

  <property>元素為類定義了一個持久化類的屬性。

name: 屬性的名字。

column (可選 - 預設為屬性名字): 對應的資料庫字段名。

type (可選): 一個NHibernate類型的名字。

update, insert (可選 - 預設為 true)

: 表明用于UPDATE 和/或 INSERT 的SQL語句中是否包含這個被映射了的字段。 這二者如果都設定為false

則表明這是一個“外源性(derived)”的屬性, 它的值來源于映射到同一個(或多個)

字段的某些其他屬性,或者通過一個trigger(觸發器)或其他程式生成。

formula (可選): 一個SQL表達式,定義了這個計算 (computed)

屬性的值。計算屬性沒有和它對應的資料庫字段。

access (可選 - 預設值為 property):

NHibernate用來通路屬性值的政策。

(7)

optimistic-lock (可選 - 預設為 true):

指定這個屬性在做更新時是否需要獲得樂觀鎖定(optimistic lock)。

換句話說,它決定這個屬性發生髒資料時版本(version)的值是否增長。

(8)

generated (可選 - 預設為 never):

表明此屬性值是否實際上是由資料庫生成的。 請參閱的讨論。

 typename可以是如下幾種

NHibernate基本類型名(比如:Int32, String, Char, DateTime,

Timestamp, Single, Byte[], Object, ...)。

一個.Net類的名字,這個類屬于一種預設基礎類型 (比如: System.Int16,

System.Single, System.Char, System.String, System.DateTime, System.Byte[],

...)。

一個枚舉類型的名字。(比如:. eg.Color)。

一個可以序列化的.NET類的名字。

一個自定義類型的類的名字。(比如: Illflow.Type.MyCustomType)。

  注意你必須為所有類型(除了NHibernate基礎類型)指定完整的應用程式集權限定名 (或者是在<hibernate-mapping>裡面配置了assembly和namespace屬性)。

  NHibernate支援.NET 2.0的可空類型,這些類型和對應的非可空類型處理方式是一緻的, 例如:Nullable<Int32>可以對應type="Int32"或者是type="System.Int32"。

  如果你沒有指定類型,NHibernate會使用反射來得到這個名字的屬性,

以此來猜測正确的NHibernate類型。NHibernate會對屬性讀取器(getter方法)的傳回類進行解釋, 按照規則2,3,4的順序。然而,這并不足夠。

在某些情況下你仍然需要type屬性。 (比如,為了差別NHibernateUtil.DateTime和NHibernateUtil.Timestamp,或者為了指定一個自定義類型。)

  access屬性用來讓你控制NHibernate如何在運作時通路屬性。 在預設情況下,

NHibernate會按照access-strategy.naming-strategy來格式化屬性名 .naming-strategy不是必填項。

 表 5.1. 通路政策

<col>

通路政策名

描述

property

預設實作:NHibernate通路類的set/get屬性,這種方式沒有命名政策,因為name就代表屬性的名稱。

field

NHibernate将會直接通路成員變量。NHibernate使用name作為成員變量的名稱。

當對象屬性的get和set裡面有額外的操作,而你不想讓NHibernate設定或者讀取對象時執行額外的操作,

可以用這個政策。當你使用HQL時需要屬性名而非字段時,就需要命名政策(Naming Strateg)。

nosetter

NHibernate将會在設定值時直接通路字段,獲得值時通路屬性。 當API使用者不能直接改變值,因而隻為屬性隻提供了get通路器時,

你可以用這個政策。NHibernate使用name屬性(attribute)作為屬性(Property ),

并且需要提供字段名,是以命名政策必須(Naming Strategy)使用。

ClassName

如果NHibernate内置的通路政策(Access Strategie)不能滿足你的要求。

你可以通過實作NHibernate.Property.IPropertyAccessor接口來自己的通路政策(Access Strategie)。

這個值需要用程式集名(Assembly)來限定,這樣就能通過 Activator.CreateInstance(string

AssemblyQualifiedName)來讀取。

  命名政策(Naming Strategy)

命名政策

camelcase

name屬性被轉換CamelCase格式來查找字段。&lt;property name="Foo"

... &gt;使用foo字段。

camelcase-underscore

name屬性被轉換CamelCase格式并添加下劃線字首來查找字段。&lt;property

name="Foo" ... &gt;使用_foo字段。

lowercase

name屬性被轉換小寫格式來查找字段。&lt;property name="FooBar" ...

&gt; 使用 foobar字段.

lowercase-underscore

name屬性被轉換小寫格式并添加下劃線字首來查找字段。&lt;property

name="FooBar" ... &gt;使用_foobar字段.

pascalcase-underscore

name屬性添加下劃線字首來查找字段。&lt;property name="Foo" ...

&gt;使用_Foo字段。

pascalcase-m

name屬性添加字母m字首來查找字段。&lt;property name="Foo" ...

&gt;使用mFoo字段。

pascalcase-m-underscore

name屬性添加字母m和下劃線字首來查找字段。&lt;property name="Foo" ...

&gt; 使用m_Foo字段。

   通過 many-to-one元素,可以定義一種常見的與另一個持久化類的關聯。這種關系模型是多對一關聯。(實際上是一個對象引用。)

name:屬性名。

column資料庫字段名

class(可選 - 預設是通過反射得到屬性類型): 關聯的類的名字。

cascade(級聯) (可選): 指明哪些操作會從父對象級聯到關聯的對象。

fetch (可選 - 預設為 select):

在外連接配接抓取(outer-join fetching)和序列選擇抓取(sequential select fetching)兩者中選擇其一。

(可選 - defaults to true) 指定對應的字段是否包含在用于UPDATE 和/或 INSERT

的SQL語句中。如果二者都是false,則這是一個純粹的 “外源性(derived)”關聯,它的值是通過映射到同一個(或多個)字段的某些其他屬性得到

或者通過trigger(觸發器)、或其他程式。

property-ref: (可選) 指定關聯類的一個屬性,這個屬性将會和本外鍵相對應。

如果沒有指定,會使用對方關聯類的主鍵。

access(可選 - 預設是 property):

NHibernate用來通路屬性的政策。

(9)

unique (可選): 使用DDL為外鍵字段生成一個唯一限制。此外,

這也可以用作property-ref的目标屬性。這使關聯同時具有 一對一的效果。

(10)

optimistic-lock (可選 - 預設為 true):

(11)

not-found (可選 - 預設為 exception):

指定外鍵引用的資料不存在時如何處理: ignore會将資料不存在作為關聯到一個空對象(null)處理。

  cascade屬性允許下列值:: all, save-update, delete, none.

設定除了none以外的其它值會傳播特定的操作到關聯的(子)對象中。參見後面的“Lifecycle Objects(自動管理生命周期的對象)”。

  fetch參數允許下列兩個不同值:

join外連接配接抓取

select使用隔離查詢抓取

  一個典型的簡單many-to-one 定義例子:

  property-ref屬性隻應該用來對付老舊的資料庫系統,

可能有外鍵指向對方關聯表的是個非主鍵字段(但是應該是一個惟一關鍵字)的情況下。 這是一種十分醜陋的關系模型。比如說,假設Product類有一個惟一的序列号,

它并不是主鍵。(unique屬性控制NHibernate通過SchemaExport工具生成DDL的過程。)

那麼關于OrderItem 的映射可能是:

 當然,我們決不鼓勵這種用法。

   持久化對象之間一對一的關聯關系是通過 one-to-one元素定義的。

class (可選 - 預設是通過反射得到的屬性類型):被關聯的類的名字。

cascade(級聯) (可選) 表明操作是否從父對象級聯到被關聯的對象。

constrained(限制) (可選)

表明該類對應的表對應的資料庫表,和被關聯的對象所對應的資料庫表之間,通過一個外鍵引用對主鍵進行限制。

這個選項影響Save()和Delete()在級聯執行時的先後順序以及 決定該關聯能否被委托(也在schema export

tool中被使用).

fetch (可選 - 預設設定為select):

在外連接配接抓取或者序列選擇抓取選擇其一.

property-ref: (可選)

指定關聯類的屬性名,這個屬性将會和本類的主鍵相對應。如果沒有指定,會使用對方關聯類的主鍵。

  有兩種不同的一對一關聯:

主鍵關聯

惟一外鍵關聯

  主鍵關聯不需要額外的表字段;如果兩行是通過這種一對一關系相關聯的,那麼這兩行就共享同樣的主關鍵字值。是以如果你希望兩個對象通過主鍵一對一關聯,你必須确認它們被賦予同樣的辨別值!

  比如說,對下面的Employee和Person進行主鍵一對一關聯:

  現在我們必須確定PERSON和EMPLOYEE中相關的字段是相等的。我們使用一個被成為foreign的特殊的現在我們必須確定PERSON和EMPLOYEE中相關的字段是相等的。我們使用一個被成為foreign的特殊的hibernate辨別符生成政策:辨別符生成政策: foreign:

  一個剛剛儲存的Person執行個體被賦予和該Person的employee屬性所指向的Employee執行個體同樣的關鍵字值。

另一種方式是一個外鍵和一個惟一關鍵字對應,上面的Employee和Person的例子,如果使用這種關聯方式,可以表達成:

 如果在Person的映射加入下面幾句,這種關聯就是雙向的: