天天看點

[NHibernate]O/R Mapping基礎

<a href="http://www.cnblogs.com/wolf-sun/p/3694592.html">[nhibernate]體系結構</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3694901.html">[nhibernate]isessionfactory配置</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3704012.html">[nhibernate]持久化類(persistent classes)</a>

對象和關系資料庫之間的映射是用一個xml文檔(xml document)來定義的。這個映射文檔被設計為易讀的,并且拒絕惡意手工修改。映射語言以.net為中心的,意味着映射是持久化類的定義來建立的,而非表的定義。 請注意,雖然很多hibernate使用者選擇手工定義xml映射文檔,也有一些工具來生成映射文檔,包括xdoclet,middlegn和andromda(這裡是nhibernate文檔中移除沒有從hibernate文檔中轉換過來的部分),nhibernate中并沒有像xdoclet,middlegn和andromda這樣的工具,在運用中,一般使用代碼生成器來生成xml配置文檔。
[NHibernate]O/R Mapping基礎
[NHibernate]O/R Mapping基礎

我們隻描述nhibernate在運作時用到的文檔元素和屬性。映射文檔包括一些額外的可選屬性和元素,他們在使用schema導出工具的時候會影響導出的資料庫schema結果。(比如,not-null屬性。)

所有的xml映射都需要使用nhibenate-mapping-2.0 schema。目前schema可以在nhibernate的資源路徑或者是nhibernate.dll的嵌入資源(embeddedresource)中找到。nhibernate總是會優先使用嵌入在資源中的schema檔案。

在使用visualstudio.net時,你應該将hibernate-mapping拷貝到c:\programfiles\microsoft visual studio.net2003\common7\packages\schemas\xml路徑中,以擷取智能感覺功能。或者在解決方案中,建立一個解決方案檔案夾,将hibernate-mapping拷入該解決方案檔案夾中也可以獲得智能感覺功能。

這個元素包括四個可選的屬性。schema屬性,指明了這個映射所引用的表所在的schema名稱。假若指定了這個屬性,表名會加上所指定的schema的名字擴充schema的名字擴充為全限定名。假若沒有指定,表明就不會使用全限定名。default-cascade指定了未注明cascade屬性和集合類會采用什麼樣的預設級聯風格。auto-import屬性預設讓我們在查詢語言中可以使用非全限定名的類名。default-access告訴我們怎麼通路屬性。

[NHibernate]O/R Mapping基礎
[NHibernate]O/R Mapping基礎

(1)schema(可選):資料庫schema名稱。

(2)default-cascade(可選-預設為none):預設的級聯風格。

(3)auto-import(可選-預設為true):指定是否我們可以在查詢語言中使用非全限定的類名(僅限于本映射檔案中的類)。

(4)default-acess(可選-預設為property):nhibernate通路屬性時的政策。

(5)assembly(可選):指定一個程式集,如果在映射文檔中沒有指定程式集,就使用這個程式集。

(6)namespace(可選):指定一個命名空間字首,如果在一個映射文檔中沒有指定全限定名,就使用這個命名空間名。

假若你有兩個持久化類,他們的非全限定名是一樣的(就是在不同的命名空間裡面),你應該設定auto-import=“false”。假若說你把一個“import過”的名字同時對應兩個類,nhibernate會抛出一個異常。

可以使用class元素來定義一個持久化類:

[NHibernate]O/R Mapping基礎
[NHibernate]O/R Mapping基礎

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

(2)table:對應的資料庫表名。

(3)discriminator-value(可選-預設和類名一樣):一個用于區分不同的子類的值,在多态行為時使用。

(4)mutable(可選,預設為true):表明該類的執行個體可變(不可變)。

(5)schema(可選):覆寫在根&lt;hibernate-mapping&gt;元素中指定的schema名字。

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

(7)dynamic-update(可選,預設為false):指定用于update的sql将會在運作時動态生成,并且隻更新哪些改變過的字段。

(8)dynamic-insert(可選,預設為false):指定用于insert的sql将會在運作時動态生成,并且隻包含哪些非空字段。

(9)polymorphism(可選,預設為implicit(隐式)):界定是隐式還是顯式的使用查詢多态。

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

(11)persister(可選):指定一個定制的iclasspersister。

(12)lazy(可選):假若設定lazy=“true”,就是設定這個類自己的名字作為proxy接口的一種等價快捷方式。

若指明的持久化類實際上是一個接口,也可以被完美的接受。其後你可以用&lt;subclass&gt;來指定該接口的實際實作類名。你可以持久化任static(靜态的)内部類。記得應該使用标準的類名格式,就是說比如:eg.foo+bar.

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

可選的proxy屬性可以允許延遲加載類的持久化執行個體。nhibernate開始會傳回實作了這個命名接口或者子類(通過的castle.dynamicproxy)。當代理的某個方法被實際調用的時候,真實的持久化對象才會被裝載。參見下面的“用于延遲加載的代理”。

implicit(隐式)的多态是指,如果查詢中給出的是任何超類,該類實作的接口或者該類的名字,都會傳回這個類的執行個體;如果查詢中給出的是子類的名字,則會傳回子類的執行個體。explicit(顯式)的多态是指,隻有在查詢中給出的明确是該類的名字時才會傳回這個類的執行個體;同時隻有當在這個&lt;class&gt;的定義中作為&lt;subclass&gt;或者&lt;joined-subclass&gt;出現的子類,才可能傳回。大多數情況下,預設的polymorphism=“implicit”都是合适的。顯式的多态在有兩個不同的類映射到同一個表的時候很有用。(允許一個“輕型”的類,隻包含部分表字段)。

persister屬性尅可讓你定制的這個類使用的持久化政策。你可以指定你自己實作的nhibernate.persister.entitypersister的子類,你甚至可以完全從頭開始編寫一個nhibernate.persister.iclasspersister接口的實作,可能是用存儲過程調用、序列互到檔案或者ldap資料庫來實作。參閱nhibernate.domainmodel.custompersister,這是一個簡單的例子(“持久化”到一個hashtable)。

請注意dynamic-update和dynamic-insert的設定并不會繼承到子類,是以在&lt;subclass&gt;或者&lt;joined-subclass&gt;元素中可能需要再次設定。這些設定是否能夠提高效率要視情況而定。

被映射的類必須聲明對應資料表主鍵字段。大多數類有一個屬性,為每一個實作包含唯一的辨別。&lt;id&gt;元素定義了該屬性到資料庫表主鍵字段的映射。

[NHibernate]O/R Mapping基礎
[NHibernate]O/R Mapping基礎

(1)name(可選):辨別屬性的名字。

(2)type(可選):辨別nhibernate類型的名字。

(3)column(可選-預設為屬性名):主鍵字段的名字。

(4)unsaved-value(可選-預設為null):一個特定的辨別屬性值,用來辨別該執行個體是剛剛建立的,尚未儲存。這可以把這種執行個體和從以前的sssion中裝載過(可能又做過修改)但未再次持久化的執行個體區分開來。

(5)access(可選-預設為property):nhibernate用來通路屬性值的政策。

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

unsaved-value屬性很重要!如果你的類的辨別屬性不是預設為null的,你應該指定正确的預設值。特别重要的是在使用值類型system.valuetype,例如system.int32或者system.guid作為你的&lt;id&gt;屬性時確定清楚的設定這個屬性,因為system.valuetype對象不可能為null值。

還有一個另外的&lt;composite-id&gt;聲明可以通路舊式的多主鍵資料。不鼓勵使用這種方式。

 必須聲明的&lt;generator&gt;子元素是一個.net類的名字,用來為該持久化類的屬性生成唯一的辨別。如果這個生成器執行個體需要某些配置值或者初始化參數,用&lt;param&gt;元素傳遞。

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

identity

對db2,mysql, ms sql server, sybase和hypersonicsql的内置辨別字段提供支援。傳回的辨別符是 int64, int32 或者 int16類型的。

sequence(序列)

對db2,mysql, postgresql, oracle的内置辨別字段提供支援。傳回的辨別符是int64 int32 或者 int16類型的。

hilo(高低位)

使用一個高/低位算法來高效的生成int64, int32 或者 int16類型的辨別符。給定一個表和字段(預設分别是hibernate_unique_key 和next)作為高位值得來源。高/低位算法生成的辨別符隻在一個特定的資料庫中是唯一的。

seqhilo(使用序列的高低位)

使用一個高/低位算法來高效的生成int64, int32 或者 int16類型的辨別符,給定一個資料庫序列(sequence)的名字。

uuid.hex

用一個system.guid和它的tostring(string format)方法生成字元串類型的辨別符。字元串的長度取決于 format的配置。

uuid.string

用一個新的system.guid産生一個byte[] ,把它轉換成字元串。

guid

用一個新的system.guid 作為辨別符。

guid.comb

用jimmy nilsson在文章http://www.informit.com/articles/article.asp?p=25862中描述的算法産生一個新的system.guid。

native(本地)

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

assigned(程式設定)

讓應用程式在save()之前為對象配置設定一個标示符。

foreign(外部引用)

使用另外一個相關聯的對象的辨別符。和&lt;one-to-one&gt;聯合一起使用。

hilo和seqhilo生成器給出了兩種hi/lo算法實作,這是一種很令人滿意的辨別符生成算法。第一種實作需要一個“特殊”的資料庫表來儲存下一個可用的“hi”值。第二種實作使用一個oracle風格的序列(在被支援的情況下)。

[NHibernate]O/R Mapping基礎
[NHibernate]O/R Mapping基礎

很不幸,你在為nhibernate自行提供connection時無法使用hilo。hibernate必須能夠在一個新的事務中得到一個“hi”值。

uuid是通過調用guid.newguid().tostring(format)産生的。format值的設定請參考msdn文檔。預設的seperator很少也不應該被改變。format決定是否配置好的seperator,并提供自己使用。

uuid是通過調用guid.newguid().tobytearray()并且把byte[]轉換成char[],char[]作為一個16個字元組成的字元串傳回。

guid辨別符通過調用guid.newguid()産生。為了提升guids在ms sql中作為主鍵,外鍵和索引的一部分時的性能,可以使用guid.comb。在别的資料庫中使用guid.comb的好處是支援非标準的guid。

對于内部支援辨別字段的資料庫(db2,mysql,sybase,ms sql),你可以使用identity關鍵字生成。對于内部支援序列的資料庫(db2,oracle, postgresql),你可以使用sequence風格的關鍵字生成。這兩種方式對于插入一個新的對象都需要兩次sql查詢。當使用ms sql并且采用identity主鍵生成器,select scope_identity()将會被附加到insert的sql語句,因而不可避免的執行兩個不同的idbcommand。

[NHibernate]O/R Mapping基礎
[NHibernate]O/R Mapping基礎

對于跨平台開發,native政策會從identity, sequence 和hilo中進行選擇,取決于底層資料庫的支援能力。

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

因為其繼承天性,使用這種生成器政策的實體不能通過isession的saveorupdate()方法儲存。作為替代,你應該明确告知nhibernate是應該被save還是update,分别調用isession的save()或update()方法。

[NHibernate]O/R Mapping基礎
[NHibernate]O/R Mapping基礎

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

你的持久化類必須重載equals()和hashcode()方法,來實作組合的辨別符判斷等價.也必須實作serializable接口

不幸的是,這種組合關鍵字的方法意味着一個持久化類是它自己的辨別。除了對象自己之外,沒有什麼友善的“把手”可用。你必須自己初始化持久化類的執行個體,在使用組合關鍵字load()持久化狀态之前,必須填充他的聯合屬性。我們會在todo: linktocompenents 中說明一種更加友善的方法,把聯合辨別實作為一個獨立的類,下面描述的屬性隻對這種備用方法有效:

<a href="http://renrenqq.cnblogs.com/admin/#composite-id1-co">(1)</a>

name (可選): 一個元件類型,持有聯合辨別(參見下一節)。

<a href="http://renrenqq.cnblogs.com/admin/#composite-id2-co">(2)</a>

class (可選 - 預設為通過反射(reflection)得到的屬性類型): 作為聯合辨別的元件類名(參見下一節)。

<a href="http://renrenqq.cnblogs.com/admin/#composite-id3-co">(3)</a>

unsaved-value (可選 - 預設為 none): 假如被設定為any的值,就表示新建立,尚未被持久化的執行個體将持有的值。

在"一棵對象繼承樹對應一個表"的政策中,&lt;discriminator&gt;元素是必需的,它聲明了表的識别器字段。識别器字段包含标志值,用于告知持久化層應該為某個特定的行建立哪一個子類的執行個體。隻能使用如下受到限制的一些類型:string, char, int32, byte, int16, boolean, yesno, truefalse.

<a href="http://renrenqq.cnblogs.com/admin/#discriminator1-co">(1)</a>

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

<a href="http://renrenqq.cnblogs.com/admin/#discriminator2-co">(2)</a>

type (可選 - 預設為 string) 一個nhibernate字段類型的名字

<a href="http://renrenqq.cnblogs.com/admin/#discriminator3-co">(3)</a>

force (可選 - 預設為 false) "強制"nhibernate指定允許的識别器值,就算取得的所有執行個體都是根類的。

<a href="http://renrenqq.cnblogs.com/admin/#discriminator4-co">(4)</a>

insert (可選 - 預設為 true) 當識别器是被映射的元件的辨別符的一部分時設定為false。

辨別器字段的實際值是根據&lt;class&gt; 和&lt;subclass&gt;元素的discriminator-value得來的。

orm深入學習。

本文來自

《nhibernate中文文檔》

部落格位址:

<a href="http://www.cnblogs.com/wolf-sun">http://www.cnblogs.com/wolf-sun/</a>

部落格版權:

本文以學習、研究和分享為主,歡迎轉載,但必須在文章頁面明顯位置給出原文連接配接。

如果文中有不妥或者錯誤的地方還望高手的你指出,以免誤人子弟。如果覺得本文對你有所幫助不如【推薦】一下!如果你有更好的建議,不如留言一起讨論,共同進步!

再次感謝您耐心的讀完本篇文章。

轉載:http://www.cnblogs.com/wolf-sun/p/3705229.html