NHibernate之映射文件配置說明


1. hibernate-mapping

  這個元素包括以下可選的屬性。 schema屬性,指明了這個映射所引用的表所在的schema名稱。假若指定了這個屬性, 表名會加上所指定的schema的名字擴展為全限定名。假若沒有指定,表名就不會使用全限定名。 default-cascade 指定了未明確注明 cascade屬性的.Net屬性和集合類.Net會采取什么樣的默認級聯風格。 auto-import屬性默認讓我們在查詢語言中可以使用非全限定名的類名。 assembly namespace指定了持久化類的應用程序集名稱和其所在的名稱空間名。
<hibernate-mapping                                   
     schema="schemaName"                   (1) 
     default-cascade="none|save-update"    (2)
     auto-import="true|false"              (3)
     assembly="Eg"                         (4)
    namespace="Eg"                         (5)
 />            

  各選項說明:

(1)

schema (optional): 數據庫schema名稱。

(2)

default-cascade (可選 - 默認為 none): 默認的級聯風格。

(3)

auto-import (optional - defaults to true): 指定我們在使用查詢語句的時候是否可以使用非全限定名。

(4)(5)

assembly and namespace(可選): 指定映射文件中的類的應用程序集名稱和其所在的名稱空間名,用來生成類的非全限定名。

  如果沒有設置assemblynamespace標簽,我們不得不使用類的非全限定名 (namespace.類名,assembly).

  假若你有兩個持久化類,它們的非全限定名是一樣的,你應該設置auto-import="false"。 假若說你把一個“import過”的名字同時對應兩個類, NHibernate會拋出一個異常。

二. class

 你可以使用 class元素來定義一個持久化類:
<class                                               
    name="ClassName"                             (1)    
    table="tableName"                            (2)
    discriminator-value="discriminator_value"    (3)
    mutable="true|false"                         (4)
    schema="owner"                               (5)
    proxy="ProxyInterface"                       (6)
    dynamic-update="true|false"                  (7)  
    dynamic-insert="true|false"                  (8)
    select-before-update="true|false"            (9) 
    polymorphism="implicit|explicit"             (10)
    where="arbitrary sql where condition"        (11)  
    persister="PersisterClass"                   (12)
    batch-size="N"                               (13)
    optimistic-lock="none|version|dirty|all"     (14) 
    lazy="true|false"                            (15)
    abstract="true|false"              (16)
/>

 各選項說明:

(1)

name: 持久化類(或者接口)的.NET全限定名。

(2)

table: 對應的數據庫表名。

(3)

discriminator-value(辨別值) (可選 - 默認和類名一樣):一個用於區分不同的子類的值,在多態行為時使用。可選值包括nullnot null

(4)

mutable (可選, 默認值為 true): 表明該類的實例可變(不可變)。

(5)

schema (可選) 覆蓋在根元素中指定的schema名字。

(6)

proxy (可選)指定一個接口,在延遲裝載時作為代理使用。你可以在這里使用該類自己的名字。

(7)

dynamic-update (可選,默認為false): 指定用於UPDATE 的SQL將會在運行時動態生成,並且只更新那些改變過的字段。

(8)

dynamic-insert (可選, 默認為false): 指定用於 INSERT的 SQL 將會在運行時動態生成,並且只包含那些非空值字段。

(9)

select-before-update (可選,默認值為 false): 指定NHibernate除非確定對象的確被修改了,UPDATE操作。在特定場合(實際上,只會發生在一個臨時對象關聯到一個新的session中去,執行update()的時候),這說明NHibernate會在UPDATE之前執行一次額外的SQL SELECT操作,來決定是否應該進行UPDATE。

(10)

polymorphism (可選, 默認值為 implicit (隱式)): 界定是隱式還是顯式的使用查詢多態。

(11)

where (可選) 指定一個附加的SQL WHERE 條件,在抓取這個類的對象時會一直增加這個條件。

(12)

persister (可選): 指定一個定制的 IClassPersister

(13)

batch-size (可選,默認是1) 指定一個用於根據標識符抓取實例時使用的"batch size"(批次抓取數量)。

(14)

optimistic-lock (樂觀鎖定) (可選,默認是version): 決定樂觀鎖定的策略。

(15)

lazy (可選): 假若設置lazy="false",就會禁用延遲加載。

(16)

abstract(可選) 用於在<union-subclass>的繼承結構 (hierarchies)中標識抽象超類。

  若指明的持久化類實際上是一個接口,這也是完全可以接受的。 之后你可以用元素 <subclass>來指定該接口的實際實現類。 你可以持久化任何static(靜態的)內部類。 你應該使用標准的類名格式來指定類名,比如:Eg.Foo+Bar, Eg。由於HQL解析器的限制NHibernate 1.0 無法在查詢里使用內部類。

  不可變類 mutable="false"不可以被應用程序更新或者刪除。 這可以讓NHibernate做一些小小的性能優化。

  可選的proxy屬性允許延遲加載類的持久化實例。 NHibernate開始會返回實現了這個命名接口的代理類。當代理的某個方法被實際調用的時候, 真實的持久化對象才會被裝載。參見下面的“用於延遲裝載的代理”。

  Implicit (隱式)的多態是指,如果查詢時給出的是任何超類、該類實現的接口或者該類的 名字,都會返回這個類的實例;如果查詢中給出的是子類的名字,則會返回子類的實例。 Explicit (顯式)的多態是指,只有在查詢時給出明確的該類名字時才會返回這個類的實例; 同時只有在這個<class>的定義中作為<subclass>或者<joined-subclass>出現的子類,才會可能返回。 在大多數情況下,默認的polymorphism="implicit"都是合適的。 顯式的多態在有兩個不同的類映射到同一個表的時候很有用。(允許一個“輕型”的類,只包含部分表字段)。

  persister屬性可以讓你定制這個類使用的持久化策略。 你可以指定你自己實現 NHibernate.Persister.EntityPersister的子類,你甚至可以完全從頭開始編寫一個 NHibernate.Persister.IClassPersister接口的實現, 比如是用儲存過程調用、序列化到文件或者LDAP數據庫來實現。 參閱NHibernate.DomainModel.CustomPersister,這是一個簡單的例子 (“持久化”Hashtable)。

  請注意dynamic-updatee和dynamic-insert的設置並不會繼承到子類, 所以在<subclass>或者<joined-subclass>元素中可能 需要再次設置。這些設置是否能夠提高效率要視情形而定。請用你的智慧決定是否使用。

  使用select-before-update通常會降低性能。如果你重新連接一個脫管(detache)對象實例 到一個Session中時,它可以防止數據庫不必要的觸發update。 這就很有用了。

如果你打開了dynamic-update,你可以選擇幾種樂觀鎖定的策略:

  • version(版本檢查) 檢查version/timestamp字段
  • all(全部) 檢查全部字段
  • dirty(臟檢查)只檢察修改過的字段
  • none(不檢查)不使用樂觀鎖定

  我們非常強烈建議你在NHibernate中使用version/timestamp字段來進行樂觀鎖定。 對性能來說,這是最好的選擇,並且這也是唯一能夠處理在session外進行操作的策略(例如: 在使用ISession.Update()的時候)。注意version或者是timestamp屬性不能為null,不管是否使用了unsaved-value策略,或者是實例被作為是瞬態。

  從NHibernate 1.2.0開始,版本號從1開始(以前的版本從0開始),這樣允許把version的屬性的unsaved-value設置為0。

三、 id

 被映射的類必須定義對應數據庫表主鍵字段。大多數類有一個屬性, 為每一個實例包含唯一的標識。 元素定義了該屬性到數據庫表主鍵字段的映射。
<id                                             
        name="PropertyName"                        (1)   
        type="typename"                             (2)
        column="column_name"                         (3)
        unsaved-value="any|none|null|id_value"       (4)
        access="field|property|nosetter|ClassName">   (5)
    
<generator class="generatorClass"/>
</id>
  說明:
(1)

name (可選): 標識屬性的名字。

(2)

type(可選): 標識NHibernate類型的名字。

(3)

column(可選 - 默認為屬性名): 主鍵字段的名字。

(4)

unsaved-value (可選 - 默認為一個切合實際(sensible)的值): 一個特定的標識屬性值,用來標志該實例是剛剛創建的,尚未保存。 這可以把這種實例和從以前的session中裝載過(可能又做過修改--譯者注) 但未再次持久化的實例區分開來。

(5)

access (可選 - 默認為property): NHibernate用來訪問屬性值的策略。

  如果name屬性不存在,會認為這個類沒有標識屬性。

四、(主鍵生成策略)generator

  可選的<generator>子元素是一個.NET類的名字, 用來為該持久化類的實例生成唯一的標識。如果這個生成器實例需要某些配置值或者初始化參數, 用元素來傳遞。

<id name="Id" type="Int64" column="uid" unsaved-value="0">
    <generator class="NHibernate.Id.TableHiLoGenerator">
        <param name="table">uid_table</param>
        <param name="column">next_hi_value_column</param>
    </generator>
</id>

  所有的生成器都實現NHibernate.Id.IIdentifierGenerator接口。 這是一個非常簡單的接口; 某些應用程序可以選擇提供他們自己特定的實現。當然, NHibernate提供了很多內置的實現。下面是一些內置生成器的快捷名字:

  1、increment

用於為int類型生成 唯一標識。只有在沒有其他進程往同一張表中插入數據時才能使用。 在集群下不要使用

  2、identity

對DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的內置標識字段提供支持。數據庫返回的主鍵值 返回的標識符是int類型的。

  3、sequence

在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的標識符是int類型的。

  4、hilo

  使用一個高/低位算法來高效的生成int類型的標識符。給定一個表和字段(默認分別是是hibernate_unique_key 和next_hi)作為高位值得來源。 高/低位算法生成的標識符只在一個特定的數據庫中是唯一的。在用戶自行提供的連接中,不要使用這種生成器。

  5、seqhilo

使用一個高/低位算法來高效的生成int類型的標識符,給定一個數據庫序列(sequence)的名字。

  6、uuid.hex

用一個System.Guid的ToString()方法法生成字符串類型的標識符, 字符串的長度由format參數定義。

  7、uuid.string

用一個新的System.Guid實例的byte[]轉化為字符串作為標示符。

  8、guid

使用新的System.Guid實例作為標示符。

  9、guid.comb

使用Jimmy Nilsson的算法(請參閱http://www.informit.com/articles/article.asp?p=25862)生成一個新的System.Guid標示符。

  10、native

根據底層數據庫的能力選擇identity, sequence 或者hilo中的一個。

  11、assigned

讓應用程序在 Save()之前為對象分配一個標示符。

  12、foreign

使用另外一個相關聯的對象的標識符。通常和<one-to-one>聯合起來使用。

  高/低位算法(Hi/Lo Algorithm)

  hilo 和 seqhilo生成器給出了兩種hi/lo算法的實現, 這是一種很令人滿意的標識符生成算法。 第一種實現需要一個“特殊”的數據庫表來保存下一個可用的“hi”值。 第二種實現使用一個Oracle風格的序列(在被支持的情況下)。
<id name="Id" type="Int64" column="cat_id">
        <generator class="hilo">
                <param name="table">hi_value</param>
                <param name="column">next_value</param>
                <param name="max_lo">100</param>
        </generator>
</id>
<id name="Id" type="Int64" column="cat_id">
        <generator class="seqhilo">
                <param name="sequence">hi_value</param>
                <param name="max_lo">100</param>
        </generator>
</id>

  很不幸,你在為NHibernate自行提供IDbConnection時無法使用hilo。 NHibernate必須能夠在一個事務里獲取"hi"值。

  UUID算法(UUID Algorithm )

<id name="Id" type="String" column="cat_id">
        <generator class="uuid.hex">
            <param name="format">format_value</param>
            <param name="seperator">seperator_value</param>
        </generator>
</id>

  UUID算法是調用Guid.NewGuid().ToString(format)方法生成標示符。 format參數的使用請參閱MSDN,GUID的默認分隔符是-, 這個基本不會改動。format可以決定是都替換默認的默認分隔符。 The UUID is generated by calling Guid.NewGuid().ToString(format)

   UUID字符串算法

   這個算法調用 Guid.NewGuid().ToByteArray()方法獲取 byte[], 然后將 byte[]轉換為 char[]char[]被作為一個長度 為16的字符串返回。

  GUID 算法

    guid標示符通過調用 Guid.NewGuid()創建。當在MSSQL中使用Guids標示符時做主鍵,外鍵或者是索引是為了獲取更好的性能 通常使用 guid.comb。其他支持GUIDs標示的的數據庫使用 guid.comb能否獲得性能的提升未知。

  標識字段和序列(Identity columns and Sequences)

  對於內部支持標識字段的數據庫(DB2,MySQL,Sybase,MS SQL),你可以使用identity關鍵字生成。 對於內部支持序列的數據庫(DB2,Oracle, PostgreSQL, Interbase, McKoi,SAP DB), 你可以使用sequence風格的關鍵字生成。 這兩種方式對於插入一個新的對象都需要兩次SQL查詢。
<id name="Id" type="Int64" column="uid">
        <generator class="sequence">
                <param name="sequence">uid_sequence</param>
        </generator>
</id>
<id name="Id" type="Int64" column="uid" unsaved-value="0">
        <generator class="identity"/>
</id>

  對於跨平台開發,native策略會從identity, sequence 和hilo中進行選擇,選擇哪一個,這取決於底層數據庫的支持能力。

  程序分配的標識符(Assigned Identifiers)

  如果你需要應用程序分配一個標示符(而非NHibernate來生成它們),你可以使用assigned生成器。 這種特殊的生成器會使用已經分配給對象的標識符屬性的標識符值。用這種特性來分配商業行為的關鍵字要特別小心(基本上總是一種可怕的設計決定)。

  因為其繼承天性,使用這種生成器策略的實體不能通過ISession的SaveOrUpdate()方法保存。作為替代, 你應該明確告知NHibernate是應該被save還是update,分別調用ISession的Save()或Update()方法。

五、composite-id 聯合ID

<composite-id
    name="PropertyName"
    class="ClassName"
    unsaved-value="any|none"
    access="field|property|nosetter|ClassName">
    <key-property name="PropertyName" type="typename" column="column_name"/>
    <key-many-to-one name="PropertyName class="ClassName" column="column_name"/></composite-id>

  如果表使用聯合主鍵,你可以把類的多個屬性組合成為標識符屬性。<composite-id> 元素接受<key-property>屬性映射和 <key-many-to-one>屬性映射作為子元素。

<composite-id>
    <key-property name="MedicareNumber"/>
    <key-property name="Dependent"/>
</composite-id>

  你的持久化類必須重載 Equals()GetHashCode()方法,來實現組合的標識符判斷等價.也必須實現可序列化

  不幸的是,這種組合關鍵字的方法意味着一個持久化類是它自己的標識。除了對象自己之外, 沒有什么方便的“把手”可用。你必須自己初始化持久化類的實例,在使用組合關鍵字load()持久化狀態之前, 必須填充他的聯合屬性。我們會在 7.4. 組件作為聯合標識符(Components as composite identifiers)第 7.4 節 “組件作為聯合標識符(Components as composite identifiers)”章中說明一種更加方便的方法, 把聯合標識實現為一個獨立的類,下面描述的屬性只對這種備用方法有效:

  • name (可選):一個組件類型,持有聯合標識(參見下一節)。

  • access (可選 - 默認為property): NHibernate應該使用的訪問此屬性值的策略

  • class (可選 - 默認為通過反射(reflection)得到的屬性類型) : 作為聯合標識的組件類名(參見下一節)。

六、鑒別器

   在"一棵對象繼承樹對應一個表"的策略中, <discriminator>元素是必需的, 它定義了表的鑒別器字段。 鑒別器字段包含標志值,用於告知持久化層應該為某個特定的行創建哪一個子類的實例。 如下這些受到限制的類型可以使用: String, Char, Int32, Byte, Short, Boolean , YesNo, TrueFalse
<discriminator
        column="discriminator_column"        (1)
        type="discriminator_type"            (2)
        force="true|false"                   (3)
        insert="true|false"                  (4)
        formula="arbitrary SQL expression"      (5)
/>
  說明:
(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表達式,用來判斷一個行數據的類型。

<discriminator formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end" type="Int32"/>

七、版本(version)(可選)

  <version> 元素是可選的,表明表中包含附帶版本信息的數據。 這在你准備使用 長事務(long transactions) 的時候特別有用。
<version
        column="version_column"                            (1)
        name="PropertyName"                                (2)
        type="typename"                                    (3)
        access="field|property|nosetter|ClassName"         (4)
        unsaved-value="null|negative|undefined|value"      (5)
        generated="never|always"                           (6)
/>

  說明:

(1)

column (可選 - 默認為屬性名): 指定持有版本號的字段名。

(2)

name 持久化類的屬性名。

(3)

type (可選 - 默認是 Int32): 版本號的類型。

(4)

access (可選 - 默認是 property): NHibernate用於訪問屬性值的策略。

(5)

unsaved-value(可選 - 默認是undefined): 用於標明某個實例時剛剛被實例化的(尚未保存)版本屬性值, 依靠這個值就可以把這種情況 和已經在先前的session中保存或裝載的脫管(detached)實例區分開來。 (undefined指明應被使用的標識屬性值。)

(6)

generated(可選 - 默認是 never): 表明此版本屬性值是否實際上是由數據庫生成的。 請參閱 5.5  “數據庫生成屬性(Generated Properties)”部分的討論。

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

八、timestamp (可選)

  可選的 <timestamp> 元素指明了表中包含時間戳數據。 這用來作為版本的替代。 時間戳本質上是一種對樂觀鎖定的一種不是特別安全的實現。當然, 有時候應用程序可能在其他方面使用時間戳。
<timestamp
        column="timestamp_column"                 (1)
        name="PropertyName"                        (2)
        access="field|property|nosetter|ClassName"    (3)
        unsaved-value="null|undefined|value"       (4)
        generated="never|always"                  (5)
/>

  說明:

(1)

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

(2)

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

(3)

access (可選 - 默認是 property): NHibernate用於訪問屬性值的策略。

(4)

unsaved-value (可選 - 默認是null): 用於標明某個實例時剛剛被實例化的(尚未保存)版本屬性值, 依靠這個值就可以把這種情況和 已經在先前的session中保存或裝載的脫管(detached)實例區分開來。 (undefined 指明使用標識屬性值進行這種判斷。)

(5)

generated : 指出時間戳值是否實際上是由數據庫生成的.請參閱5.5  “數據庫生成屬性(Generated Properties)”的討論。

  注意<timestamp>等價於 <version type="timestamp">

九、property

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

<property
        name="propertyName"                 (1)
        column="column_name"                (2)
        type="typename"                     (3)
        update="true|false"                 (4)
        insert="true|false"                 (4)
        formula="arbitrary SQL expression"  (5)
        access="field|property|ClassName"   (6)
        optimistic-lock="true|false"        (7)
        generated="never|insert|always"     (8)
/>

  說明:

(1)

name: 屬性的名字。

(2)

column (可選 - 默認為屬性名字): 對應的數據庫字段名。

(3)

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

(4)

update, insert (可選 - 默認為 true) : 表明用於UPDATE 和/或 INSERT 的SQL語句中是否包含這個被映射了的字段。 這二者如果都設置為false 則表明這是一個“外源性(derived)”的屬性, 它的值來源於映射到同一個(或多個) 字段的某些其他屬性,或者通過一個trigger(觸發器)或其他程序生成。

(5)

formula (可選): 一個SQL表達式,定義了這個計算 (computed) 屬性的值。計算屬性沒有和它對應的數據庫字段。

(6)

access (可選 - 默認值為 property): NHibernate用來訪問屬性值的策略。

(7)

optimistic-lock (可選 - 默認為 true): 指定這個屬性在做更新時是否需要獲得樂觀鎖定(optimistic lock)。 換句話說,它決定這個屬性發生臟數據時版本(version)的值是否增長。

(8)

generated (可選 - 默認為 never): 表明此屬性值是否實際上是由數據庫生成的。 請參閱5.5  “數據庫生成屬性(Generated Properties)”的討論。

  typename可以是如下幾種

  1. NHibernate基本類型名(比如:Int32, String, Char, DateTime, Timestamp, Single, Byte[], Object, ...)。

  2. 一個.Net類的名字,這個類屬於一種默認基礎類型 (比如: System.Int16, System.Single, System.Char, System.String, System.DateTime, System.Byte[], ...)。

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

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

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

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

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

  如果你沒有指定類型,NHibernate會使用反射來得到這個名字的屬性, 以此來猜測正確的NHibernate類型。NHibernate會對屬性讀取器(getter方法)的返回類進行解釋, 按照規則2,3,4的順序。然而,這並不足夠。 在某些情況下你仍然需要type屬性。 (比如,為了區別NHibernateUtil.DateTimeNHibernateUtil.Timestamp,或者為了指定一個自定義類型。)

  access屬性用來讓你控制NHibernate如何在運行時訪問屬性。 在默認情況下, NHibernate會按照access-strategy.naming-strategy來格式化屬性名 .naming-strategy不是必填項。

  表 5.1. 訪問策略

訪問策略名 描述
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格式來查找字段。<property name="Foo" ... >使用foo字段。

camelcase-underscore

name屬性被轉換CamelCase格式並添加下划線前綴來查找字段。<property name="Foo" ... >使用_foo字段。

lowercase

name屬性被轉換小寫格式來查找字段。<property name="FooBar" ... > 使用 foobar字段.

lowercase-underscore

name屬性被轉換小寫格式並添加下划線前綴來查找字段。<property name="FooBar" ... >使用_foobar字段.

pascalcase-underscore

name屬性添加下划線前綴來查找字段。<property name="Foo" ... >使用_Foo字段。

pascalcase-m

name屬性添加字母m前綴來查找字段。<property name="Foo" ... >使用mFoo字段。

pascalcase-m-underscore

name屬性添加字母m和下划線前綴來查找字段。<property name="Foo" ... > 使用m_Foo字段。

十、多對一(many-to-one)

   通過 many-to-one元素,可以定義一種常見的與另一個持久化類的關聯。這種關系模型是多對一關聯。(實際上是一個對象引用。)
<many-to-one
        name="PropertyName"                                (1)
        column="column_name"                               (2)
        class="ClassName"                                  (3)
        cascade="all|none|save-update|delete"              (4)
        fetch="join|select"                                (5)
        update="true|false"                                (6)
        insert="true|false"                                (6)
        property-ref="PropertyNameFromAssociatedClass"     (7)
        access="field|property|nosetter|ClassName"         (8)
        unique="true|false"                                (9)
        optimistic-lock="true|false"                       (10)
        not-found="ignore|exception"                       (11)
/>

  說明:

(1)

name:屬性名。

(2)

column數據庫字段名

(3)

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

(4)

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

(5)

fetch (可選 - 默認為 select): 在外連接抓取(outer-join fetching)和序列選擇抓取(sequential select fetching)兩者中選擇其一。

(6)

(可選 - defaults to true) 指定對應的字段是否包含在用於UPDATE 和/或 INSERT 的SQL語句中。如果二者都是false,則這是一個純粹的 “外源性(derived)”關聯,它的值是通過映射到同一個(或多個)字段的某些其他屬性得到 或者通過trigger(觸發器)、或其他程序。

(7)

property-ref: (可選) 指定關聯類的一個屬性,這個屬性將會和本外鍵相對應。 如果沒有指定,會使用對方關聯類的主鍵。

(8)

access(可選 - 默認是 property): NHibernate用來訪問屬性的策略。

(9)

unique (可選): 使用DDL為外鍵字段生成一個唯一約束。此外, 這也可以用作property-ref的目標屬性。這使關聯同時具有 一對一的效果。

(10)

optimistic-lock (可選 - 默認為 true): 指定這個屬性在做更新時是否需要獲得樂觀鎖定(optimistic lock)。 換句話說,它決定這個屬性發生臟數據時版本(version)的值是否增長。

(11)

not-found (可選 - 默認為 exception): 指定外鍵引用的數據不存在時如何處理: ignore會將數據不存在作為關聯到一個空對象(null)處理。

  cascade屬性允許下列值:: all, save-update, delete, none. 設置除了none以外的其它值會傳播特定的操作到關聯的(子)對象中。參見后面的“Lifecycle Objects(自動管理生命周期的對象)”。

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

  • join外連接抓取

  • select使用隔離查詢抓取

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

<many-to-one name="product" class="Product" column="PRODUCT_ID"/>

  property-ref屬性只應該用來對付老舊的數據庫系統, 可能有外鍵指向對方關聯表的是個非主鍵字段(但是應該是一個惟一關鍵字)的情況下。 這是一種十分丑陋的關系模型。比如說,假設Product類有一個惟一的序列號, 它並不是主鍵。(unique屬性控制NHibernate通過SchemaExport工具生成DDL的過程。)

<property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>

  那么關於OrderItem 的映射可能是:

<many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/>

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

十一、一對一

   持久化對象之間一對一的關聯關系是通過 one-to-one元素定義的。
<one-to-one
        name="PropertyName"                                (1)
        class="ClassName"                                  (2)
        cascade="all|none|save-update|delete"              (3)
        constrained="true|false"                           (4)
        fetch="join|select"                                (5)
        property-ref="PropertyNameFromAssociatedClass"     (6)
        access="field|property|nosetter|ClassName"         (7)
/>

  說明:

(1)

name: 屬性的名字。

(2)

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

(3)

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

(4)

constrained(約束) (可選) 表明該類對應的表對應的數據庫表,和被關聯的對象所對應的數據庫表之間,通過一個外鍵引用對主鍵進行約束。 這個選項影響Save()和Delete()在級聯執行時的先后順序以及 決定該關聯能否被委托(也在schema export tool中被使用).

(5)

fetch (可選 - 默認設置為select): 在外連接抓取或者序列選擇抓取選擇其一.

(6)

property-ref: (可選) 指定關聯類的屬性名,這個屬性將會和本類的主鍵相對應。如果沒有指定,會使用對方關聯類的主鍵。

(7)

access (可選 - 默認是 property): NHibernate用來訪問屬性的策略。

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

  • 主鍵關聯

  • 惟一外鍵關聯

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

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

<one-to-one name="Person" class="Person"/>
<one-to-one name="Employee" class="Employee" constrained="true"/>

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

<class name="Person" table="PERSON">
    <id name="Id" column="PERSON_ID">
        <generator class="foreign">
            <param name="property">Employee</param>
        </generator>
    </id>
    ...
    <one-to-one name="Employee"
        class="Employee"
        constrained="true"/>
</class>

  一個剛剛保存的Person實例被賦予和該Person的employee屬性所指向的Employee實例同樣的關鍵字值。

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

<many-to-one name="Person" class="Person" column="PERSON_ID" unique="true"/>

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

<one-to-one name="Employee" class="Employee" property-ref="Person"/>

十二、組件(component), 動態組件(dynamic-component)

  <component>元素把子對象的一些元素與父類對應的表的一些字段映射起來。 然后組件可以定義它們自己的屬性、組件或者集合。

<component 
        name="PropertyName"                               (1)
        class="ClassName"                                  (2)
        insert="true|false"                                (3)
        upate="true|false"                                 (4)
        access="field|property|nosetter|ClassName"         (5)
        optimistic-lock="true|false"                       (6)
>
        <property ...../>
        <many-to-one .... />
        ........
</component>
  說明:
(1)

name: 屬性名

(2)

class (可選 - 默認為通過反射得到的屬性類型):組件(子)類的名字。

(3)

insert: 被映射的字段是否出現在SQL的INSERT語句中?

(4)

update: 被映射的字段是否出現在SQL的UPDATE語句中?

(5)

access可選 - 默認是 property): NHibernate用來訪問屬性的策略。

(6)

optimistic-lock (可選 - 默認是 true):表明更新此組件是否需要獲取樂觀鎖。換句話說,當這個屬性變臟時,是否增加版本號(Version

  其<property>子標簽為子類的一些屬性與表字段之間建立映射。

  <component>元素允許加入一個 <parent>子元素,在組件類內部就可以有一個指向其容器的實體的反向引用。

  <dynamic-component>元素允許把一個 IDictionaryp映射為組件,其屬性名對應鍵值。 參見第 8.5 節 “動態組件 (Dynamic components)”.

十三、子類(subclass)

   最后,多態持久化需要為父類的每個子類都進行定義。 對於“每一棵類繼承樹對應一個表”的策略來說,就需要使用 <subclass>定義。
<subclass
        name="ClassName"                              (1)
        discriminator-value="discriminator_value"     (2)
        proxy="ProxyInterface"                        (3)
        lazy="true|false"                             (4)
        dynamic-update="true|false"
        dynamic-insert="true|false">

        <property .... />
        .....
</subclass>
  說明:
(1)

name: 子類的全限定名。

(2)

discriminator-value (辨別標志) (可選 - 默認為類名):一個用於區分每個獨立的子類的值。

(3)

proxy(代理) (可選): 指定一個類或者接口,在延遲裝載時作為代理使用。

(4)

lazy(可選, 默認是true): 設置為 lazy="false" 禁止使用延遲抓取。

  每個子類都應該定義它自己的持久化屬性和子類。 <version><id>屬性可以從根父類繼承下來。 在一棵繼承樹上的每個子類都必須定義一個唯一的discriminator-value。如果沒有指定,就會使用.NET類的全限定名。

十四、連接的子類(joined-subclass)

   此外,每個子類可能被映射到他自己的表中(每個子類一個表的策略)。被繼承的狀態通過和超類的表關聯得到。我們使用 <joined-subclass>元素。
<joined-subclass
        name="ClassName"                    (1)
        proxy="ProxyInterface"              (2)
        lazy="true|false"                   (3)
        dynamic-update="true|false"
        dynamic-insert="true|false">

        <key .... >

        <property .... />
        .....
</joined-subclass>
  說明:
(1)

name: 子類的全限定名。

(2)

proxy (可選): 指定一個類或者接口,在延遲裝載時作為代理使用。

(3)

lazy(可選, 默認是 true): 設置為 lazy="false" 禁止使用延遲裝載。 等價於設置proxy為自身類。

  這種映射策略不需要指定辨別標志(discriminator)字段。但是,每一個子類都必須使用 <key>元素指定一個表字段來持有對象的標識符。本章開始的映射可以被用如下方式重寫:

<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Eg"
    namespace="Eg">

        <class name="Cat" table="CATS">
                <id name="Id" column="uid" type="Int64">
                        <generator class="hilo"/>
                </id>
                <property name="BirthDate" type="Date"/>
                <property name="Color" not-null="true"/>
                <property name="Sex" not-null="true"/>
                <property name="Weight"/>
                <many-to-one name="Mate"/>
                <set name="Kittens">
                        <key column="MOTHER"/>
                        <one-to-many class="Cat"/>
                </set>
                <joined-subclass name="DomesticCat" table="DOMESTIC_CATS">
                    <key column="CAT"/>
                        <property name="Name" type="String"/>
                </joined-subclass>
        </class>

        <class name="Dog">
                <!-- mapping for Dog could go here -->
        </class>

</hibernate-mapping>

十五、聯合子類(union-subclass)

   第三種選擇是僅僅映射類繼承樹中具體類部分到表中(每個具體類一張表的策略)。 其中,每張表定義了類的所有持久化狀態,包括繼承的狀態。 在 NHibernate 中,並不需要完全顯式地映射這樣的繼承樹。 你可以簡單地使用單獨的 <class>定義映射每個類。 然而,如果你想使用多態關聯(例如,一個對類繼承樹中超類的關聯),你需要使用 <union-subclass>映射。
<union-subclass
        name="ClassName"                    (1)
        table="tablename"                   (2)
        proxy="ProxyInterface"              (3)
        lazy="true|false"                   (4)
        dynamic-update="true|false"
        dynamic-insert="true|false"
        schema="schema"
        catalog="catalog"
        extends="SuperclassName"
        abstract="true|false"
        persister="ClassName"
        subselect="SQL expression"
        entity-name="EntityName"
        node="element-name">

        <property .... />
        .....
</union-subclass>
  說明:
(1)

name: 子類的全限定名。

(2)

table: 子類的表名

(3)

proxy (可選): 指定一個類或者接口,在延遲裝載時作為代理使用。

(4)

lazy (可選, 默認是 true): 設置為 lazy="false" 禁止使用延遲裝載。

這種映射策略不需要指定辨別標志(discriminator)字段。

十六、連接(join)

   使用 <join> 元素,可以將一個類的屬性映射到多張表中。 當表之間存在一對一關系的時候使用。
<join
        table="tablename"                        (1)
        schema="owner"                           (2)
        fetch="join|select"                      (3)
        inverse="true|false"                     (4)
        optional="true|false">                   (5)

        <key ... />

        <property ... />
        ...
</join>

  說明:

(1)

table: 被連接表的名稱。

(2)

schema (可選):覆蓋由根<hibernate-mapping>元素指定的模式名稱。

(3)

fetch (可選 - 默認是 join): 如果設置為默認值join, NHibernate 將使用一個內連接來得到這個類或其超類定義的join ,而使用一個外連接來得到其子類定義的join。如果設置為select, 則 NHibernate 將為子類定義的 join使用順序選擇。 這僅在一行數據表示一個子類的對象的時候才會發生。對這個類和其超類定義的join,依然會使用內連接得到。

(4)

inverse(可選 - 默認是 false): 如果打開,NHibernate 不會插入或者更新此連接定義的屬性。

(5)

optional (可選 - 默認是 false): 如果打開,NHibernate 只會在此連接定義的屬性非空時插入一行數據,並且總是使用一個外連接來得到這些屬性。

  例如,一個人(person)的地址(address)信息可以被映射到單獨的表中(並保留所有屬性的值類型語義):

<class name="Person"
    table="PERSON">

    <id name="id" column="PERSON_ID">...</id>

    <join table="ADDRESS">
        <key column="ADDRESS_ID"/>
        <property name="address"/>
        <property name="zip"/>
        <property name="country"/>
    </join>

  此特性常常對遺留數據模型有用,我們推薦表個數比類個數少,以及細粒度的領域模型。然而,在單獨的繼承樹上切換繼承映射策略是有用的,后面會解釋這點。

十七、引用

  假設你的應用程序有兩個同樣名字的持久化類,但是你不想在Hibernate查詢中使用他們的全限定名。 除了依賴auto-import="true"以外,類也可以被顯式地“import(引用)”。你甚至可以引用沒有明確被映射的類和接口。

<import class="System.Object" rename="Universe"/>
<import
        class="ClassName"              (1)
        rename="ShortName"             (2)
/>

  說明:

(1)

class: 任何.NET類的全限定名。包括應用程序集名

(2)

rename(可選 - 默認為類的全限定名): 在查詢語句中可以使用的名字。  

十八、實體(Entities)和值(values)

   為了理解很多與持久化服務相關的.NET語言級對象的行為,我們需要把它們分為兩類:

  實體entity獨立於任何持有實體引用的對象。與通常的.Net模型相比, 不再被引用的對象會被當作垃圾收集掉。實體必須被顯式的保存和刪除(除非保存和刪除是從父實體向子實體引發的級聯)。 這和ODMG模型中關於對象通過可觸及保持持久性有一些不同——比較起來更加接近應用程序對象通常在一個大系統中的使用方法。 實體支持循環引用和交叉引用,它們也可以加上版本信息。

  一個實體的持久狀態包含指向其他實體和值類型實例的引用。值可以是原始類型,集合(不是集合中的對象), 組件或者特定的不可變對象。與實體不同,值(特別是集合和組件)是通過可觸及性來進行持久化和刪除的。 因為值對象(和原始類型數據)是隨着包含他們的實體而被持久化和刪除的,他們不能被獨立的加上版本信息。 值沒有獨立的標識,所以他們不能被兩個實體或者集合共享。

  所有的NHibernate類型(如果.NET可空)除了集合類都支持null語義(繼承System.ValueType)。

  直到現在,我們都一直使用術語“持久類”(persistent class)來代表實體。我們仍然會這么做。 然而嚴格說來,不是所有的用戶自定義的,帶有持久化狀態的類都是實體。組件就是用戶自定義類,卻是值語義的。

十九、基本值類型

   基本值類型大致可以分為3類: System.ValueType類型, System.Object類型, System.Object大對象類型,像.Net的類型一樣, System.ValueType類型不能存儲null值,而 System.Object類型可以。

表 5.3. System.ValueType映射類型

NHibernate類型 .NET類型 Database類型 備注
AnsiChar System.Char DbType.AnsiStringFixedLength - 1 char  
Boolean System.Boolean DbType.Boolean 在沒有指定類型(type) 屬性時的默認值。
Byte System.Byte DbType.Byte 在沒有指定類型(type) 屬性時的默認值。
Char System.Char DbType.StringFixedLength - 1 char 在沒有指定類型(type) 屬性時的默認值。
DateTime System.DateTime DbType.DateTime - ignores the milliseconds 在沒有指定類型(type) 屬性時的默認值。
Decimal System.Decimal DbType.Decimal 在沒有指定類型(type) 屬性時的默認值。
Double System.Double DbType.Double 在沒有指定類型(type) 屬性時的默認值。
Guid System.Guid DbType.Guid 在沒有指定類型(type) 屬性時的默認值。
Int16 System.Int16 DbType.Int16 在沒有指定類型(type) 屬性時的默認值。
Int32 System.Int32 DbType.Int32 在沒有指定類型(type) 屬性時的默認值。
Int64 System.Int64 DbType.Int64 在沒有指定類型(type) 屬性時的默認值。
PersistentEnum A System.Enum 潛在類型對應的DbType 不用在映射文件指定type="PersistentEnum".而是提供枚舉的程序集全名, 讓NHibernate用反射來猜測類型。枚舉使用的潛在類型決定適當的DbType.。
Single System.Single DbType.Single 在沒有指定類型(type) 屬性時的默認值。
Ticks System.DateTime DbType.Int64 type="Ticks"必須被指定。
TimeSpan System.TimeSpan DbType.Int64 在沒有指定類型(type) 屬性時的默認值。
Timestamp System.DateTime DbType.DateTime - 取決於數據庫支持 type="Timestamp"必須被指定。
TrueFalse System.Boolean DbType.AnsiStringFixedLength - 一個字符,'Y' 或者'N' type="TrueFalse"必須被指定。
YesNo System.Boolean DbType.AnsiStringFixedLength - 一個字符,'Y' 或者'N' type="YesNo"必須被指定。

  

NHibernate Type .NET Type Database Type Remarks
AnsiString System.String DbType.AnsiString type="AnsiString"必須被指定。
CultureInfo System.Globalization.CultureInfo DbType.String - 表明文化(culture)的5個字符 在沒有指定類型(type) 屬性時的默認值。
Binary System.Byte[] DbType.Binary 在沒有指定類型(type) 屬性時的默認值。
Type System.Type DbType.String 保存應用程序集權限定名。 在沒有指定類型(type) 屬性時的默認值。
String System.String DbType.String 在沒有指定類型(type) 屬性時的默認值。

  

NHibernate Type .NET Type Database Type Remarks
StringClob System.String DbType.String type="StringClob"必須被指定。 整個字段在內存里可讀。
BinaryBlob System.Byte[] DbType.Binary type="BinaryBlob"必須被指定。 整個字段在內存里可讀。
Serializable Any System.Object 必須標注可序列化標簽 DbType.Binary type="Serializable" 應該被指定. 如果不能為屬性找到NHibernate類型,這是最后可依靠的類型。

  NHibernate為了兼容Hibernate也支持也一些額外的Java類型名(主要是方便能夠使用Hibernate代碼生成的映射文件), tt class="literal">type="integer"被映射為Int32 NHibernateType,type="short" 被映射為Int16 NHibernateType 。你可以通過查看NHibernate.Type.TypeFactory類的靜態構造函數的代碼查看到所有的上述所有的類型轉換。

二十、自定義值類型

   開發者創建屬於他們自己的值類型也是很容易的。比如說,你可能希望持久化 Int64類型的屬性, 持久化成為 VARCHAR 字段。NHibernate沒有內置這樣一種類型。自定義類型能夠映射一個屬性(或集合元素)到不止一個數據庫表字段。 比如說,你可能有這樣的屬性: Name { get; set; },這是 String類型的,對應的持久化到三個字段: FIRST_NAME, INITIAL, SURNAME

要實現一個自定義類型,可以實現NHibernate.UserTypes.IUserTypeNHibernate.UserTypes.ICompositeUserType中的任一個, 並且使用類型的全限定類名來定義屬性。請查看 NHibernate.DomainModel.DoubleStringType這個例子,看看它是怎么做的。

<property name="TwoStrings" type="NHibernate.DomainModel.DoubleStringType, NHibernate.DomainModel">
    <column name="first_string"/>
    <column name="second_string"/>
</property>

  注意使用<column>標簽來把一個屬性映射到多個字段的做法。

  ICompositeUserType, IEnhancedUserType, INullableUserType, IUserCollectionType, 和 IUserVersionType接口為更特殊的使用方式提供支持。

  你甚至可以在一個映射文件中提供參數給一個IUserType。 為了這樣做, 你的UserType必須實現NHibernate.UserTypes.IParameterizedType接口。為了給自定義類型提供參數,你可以在映射文件中使用<type>元素。

<property name="priority">
    <type name="MyCompany.UserTypes.DefaultValueIntegerType">
        <param name="default">0</param>
    </type>
</property>

  現在,IUserType 可以從傳入的IDictionary對象中得到default 參數的值。

  盡管 NHibernate 內建的豐富的類型和對組件的支持意味着你可能很少 需要使用自定義類型。不過, 為那些在你的應用中經常出現的(非實體)類使用自定義類型也是一個好方法。例如, 一個MonetaryAmount類使用ICompositeUserType來映射是不錯的選擇,雖然他可以很容易地被映射成組件。這樣做的動機之一是抽象。使用自定義類型,以后假若你改變表示金額的方法時,它可以保證映射文件不需要修改。

二十一、任意(Any)類型映射

   這是屬性映射的又一種類型。 <any> 映射元素定義了一種從多個表到類的多態關聯。 這種類型的映射常常需要多於一個字段。第一個字段持有被關聯實體的類型,其他的字段持有標識符。 對這種類型的關聯來說,不可能指定一個外鍵約束,所以這當然不是映射(多態)關聯的通常的方式。 你只應該在非常特殊的情況下使用它(比如,審計log,用戶會話數據等等)。

  meta-type屬性使得應用程序能指定一個將數據庫字段的值映射到持久化類的自定義類型。 這個持久化類包含有用id-type指定的標識符屬性。 你必須指定從meta-type的值到類名的映射。

 <any name="being" id-type="Int64" meta-type="string">
    <meta-value value="TBL_ANIMAL" class="Animal"/>
    <meta-value value="TBL_HUMAN" class="Human"/>
    <meta-value value="TBL_ALIEN" class="Alien"/>
    <column name="table_name"/>
    <column name="id"/>
 </any>

  NHibernate也支持meta-type="class"標簽,這個例子里meta-value不是必須的, 因為 meta-value就是持久化類名(persistentClass.FullName)。

 <any name="being" id-type="Int64" meta-type="class">
    <column name="table_name"/>
    <column name="id"/>
  </any>

  但你使用meta-type="class"在查詢語句里設置參數時,你必須使用下面的代碼:

SetParameter("paramName", typeof(YourClass).FullName, NHibernateUtil.ClassMetaType)

  映射文件部分:

<any
        name="propertyName"                     (1)
        id-type="idtypename"                     (2)
        meta-type="metatypename"                 (3)
        cascade="cascade_style"                  (4)
        access="field|property|ClassName"        (5)
        optimistic-lock="true|false"             (6)
>
        <meta-value ... />
        <meta-value ... />
        .....
        <column .... />
        <column .... />
        .....
</any>

  說明:

(1)

name: 屬性名。

(2)

id-type: 標識符類型。

(3)

meta-type (可選 -默認是 string): 允許辨別標志(discriminator)映射的任何類型。

(4)

cascade (可選 -默認是none): 級聯的類型。

(5)

access (可選 -默認是 property): NHibernate 用來訪問屬性值的策略。

(6)

optimistic-lock (可選 -默認是 true): 表明更新此組件是否需要獲取樂觀鎖。換句話說,當這個屬性變臟時,是否增加版本號(Version) 。  

二十二、SQL中引號包圍的標識符

   你可強制NHibernate在生成的SQL中把標識符用引號前后包圍起來,這需要在映射文檔中使用反向引號(`)把表名或者字段名包圍(可能比較拗口,請看下面的例子)。NHibernate會使用相應的SQL Dialect(方言)來使用正確的引號風格(通常是雙引號,但是在SQL Server中是括號,MySQL中是反向引號)。
<class name="LineItem" table="`Line Item`">
    <id name="Id" column="`Item Id`"/><generator class="assigned"/></id>
    <property name="ItemNumber" column="`Item #`"/>
    ...
</class>

二十三、模塊化映射文件

   允許在獨立的映射文檔中定義 subclassjoined-subclass,直接位於 hibernate-mapping下。這就可以讓你每次擴展你的類層次的時候,加入新的映射文件就行了。在子類的映射中你必須指定一個 extends屬性,指明先前已經映射過的超類。使用這個功能的時候,一定要注意映射文件的排序是非常重要的!
<hibernate-mapping>
        <subclass name="Eg.Subclass.DomesticCat, Eg"
            extends="Eg.Cat, Eg" discriminator-value="D">
             <property name="name" type="string"/>
        </subclass>
</hibernate-mapping>

二十四、數據庫生成屬性(Generated Properties)

   Generated properties指的是其值由數據庫生成的屬性。一般來說,如果對象有任何屬性由數據庫生成值,NHibernate應用程序需要進行刷新( Refresh)。但如果把屬性標明為generated,就可以轉由NHibernate來負責這個動作。實際上。對定義了generated properties的實體,每當NHibernate執行一條SQL INSERT或者UPDATE語句,會立刻執行一條select來獲得生成的值。

  被標明為generated的屬性還必須是 non-insertable和 non-updateable的。只有(version)(可選),時間戳 (可選)和屬性可以被標明為generated。

  • never (默認) 標明此屬性值不是從數據庫中生成。
  • insert - 標明此屬性值在insert的時候生成,但是不會在隨后的update時重新生成。比如說創建日期就歸屬於這類。
  • always - 標明此屬性值在insert和update時都會被生成。 

二十五、數據庫輔助對象

   幫助CREATE和DROP任意數據庫對象,與NHibernate的schema交互工具組合起來,可以提供在NHibernate映射文件中完全定義用戶schema的能力。雖然這是為創建和銷毀trigger(觸發器)或stored procedure(存儲過程)等特別設計的,實際上任何可以在 IDbCommand.ExecuteNonQuery()方法中執行的SQL命令都可以在此使用(比如ALTER, INSERT,等等)。本質上有兩種模式來定義輔助數據庫對象。

  第一種模式是在映射文件中顯式聲明CREATE和DROP命令:

<nhibernate-mapping>
    ...
    <database-object>
        <create>CREATE TRIGGER my_trigger ...</create>
        <drop>DROP TRIGGER my_trigger</drop>
    </database-object>
</nhibernate-mapping>

  第二種模式是提供一個類,這個類知道如何組織CREATE和DROP命令。這個特別類必須實現NHibernate.Mapping.IAuxiliaryDatabaseObject接口。

<hibernate-mapping>
    ...
    <database-object>
        <definition class="MyTriggerDefinition, MyAssembly"/>
    </database-object>
</hibernate-mapping>

  你也可以在配置文件里設置參數傳給數據庫對象。

<hibernate-mapping>
    ...
    <database-object>
        <definition class="MyTriggerDefinition, MyAssembly">
            <param name="parameterName">parameterValue</param>
        </definition>
    </database-object>
</hibernate-mapping>

  NHibernate可以調用IAuxiliaryDatabaseObject.SetParameterValues方法接受dictionary參數。

  還有,這些數據庫對象可以特別指定為僅在特定的方言中才使用。

<hibernate-mapping>
    ...
    <database-object>
        <definition class="MyTriggerDefinition"/>
        <dialect-scope name="NHibernate.Dialect.Oracle9Dialect"/>
        <dialect-scope name="NHibernate.Dialect.OracleDialect"/>
    </database-object>
</hibernate-mapping>
 
                 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM