NHibernate的关键点精要
??????? 學(xué)習(xí)NHibernate,使用NHibernate總是有太多的疑惑。原來(lái)以后不就是個(gè)配置文件,后來(lái)才發(fā)現(xiàn)遠(yuǎn)遠(yuǎn)沒(méi)有那么簡(jiǎn)單,這個(gè)配置文件又要照顧Entity Class,又要照顧數(shù)據(jù)庫(kù)腳本生成,更要照顧動(dòng)態(tài)的SQL語(yǔ)句生成,所以現(xiàn)在想來(lái)碰到這么多問(wèn)題也是正常了。這些問(wèn)題,有些在同事間、或者自己琢磨已經(jīng)有結(jié)果,但是有很多問(wèn)題是直到看了孫姐姐的書(shū)《精通HIBERNATE:Java對(duì)象持久化技術(shù)詳解》,才豁然開(kāi)朗。NHibernate組織自己也說(shuō),現(xiàn)在離1.0的最終發(fā)布版本差的就是文檔了,所以NHibernate文檔的缺乏更加加深了掌握的難度,但是幸好它是Hibernate的一個(gè)port,所以學(xué)習(xí)NHibernate最好的資料就是Hibernate的各種介紹和書(shū)籍了。下面就講我認(rèn)為比較重要的一一列出了。
1、持久層開(kāi)發(fā)的最佳路線圖:hbm->entity class->database scripts
hbm是信息最豐富的,所以由它作為驅(qū)動(dòng)因素是最理想的,當(dāng)然如果是項(xiàng)目的約束的影響那就另當(dāng)別論了(比如數(shù)據(jù)庫(kù)已經(jīng)設(shè)計(jì)好了)。從hbm->entity class可以使用NHibernateContrib庫(kù)(NHibernate官方開(kāi)發(fā)的),最后生成database scripts的功能NHibernate庫(kù)已經(jīng)自帶了。寫(xiě)hbm實(shí)際上不困難,只有將NHibernate自帶的幾個(gè)xsd文件拷貝到VS相應(yīng)目錄下就可以使用智能提醒了,寫(xiě)起來(lái)可謂是運(yùn)指如飛。另外有個(gè)叫Object Mapper的工具提供了從UML圖自動(dòng)生成hbm的功能,不過(guò)我試了一下不是很爽,沒(méi)有直接寫(xiě)快。
2、要Lazy Load,還是要清晰的DAL Service層?
(N)Hibernate一再?gòu)?qiáng)調(diào)Lazy Load的重要性,所他如何可以增加程序的性能,但是經(jīng)過(guò)一段時(shí)間的研究發(fā)現(xiàn)Lazy Load固然好,但是可能會(huì)破壞企業(yè)應(yīng)用架構(gòu)。首先Lazy Load的使用有一個(gè)前提就是必須在同一個(gè)Session中,否則NHibernate給Lazy Load的類加的動(dòng)態(tài)代理的事前攔截將無(wú)法捕獲合適的Session因此在后來(lái)讀Lazy Load的屬性時(shí)會(huì)去用已經(jīng)關(guān)閉的Session,自然就會(huì)throw exception了。另外,按照依賴顛倒的原則,一般我們都這樣來(lái)BLL層下的架構(gòu)“BLL ----> IDAL <--- DALImpl”,那么在DAL的每個(gè)方法中,必須經(jīng)歷Session打開(kāi)和關(guān)閉的過(guò)程,因此當(dāng)BLL層獲得某個(gè)持久類,實(shí)際上是游離狀態(tài)的,即Session已經(jīng)關(guān)閉,此時(shí)BLL層在去讀設(shè)置了Lazy Load的屬性,就注定失敗了。那么如何才能應(yīng)用Lazy Load?一個(gè)辦法在BLL中用NHiberante的Session等,但這樣顯然破壞了原本清晰的架構(gòu)。所以我的理解是:Lazy Load和清晰的DAL Service層,二者不可兼得。當(dāng)然最好是我理解錯(cuò)了,:)
3、inverse屬性
該屬性通常存在于雙向管理關(guān)系中的<set>等列表標(biāo)簽中,其含義是“是否是鏡像”的含義。比如在many-to-one雙向關(guān)聯(lián)關(guān)系中One方的<set>標(biāo)簽中若設(shè)置了inverse=true,則表示One方的關(guān)系設(shè)定只是一個(gè)鏡像,而該關(guān)系的最終生成SQL則完全用Many方?jīng)Q定。因此當(dāng)運(yùn)行一下腳本:
2Many?theMany?=?one?Many();
3
4//?此處省略常規(guī)屬性的賦值
5
6theOne.TheMany?=?theMany;
7theMany.OneList.Add(theOne);數(shù)據(jù)庫(kù)只會(huì)生成一條插入到TableMany中INSERT語(yǔ)句。
如果將One方<set>標(biāo)簽中的inverse屬性改成false,則就會(huì)生成2條SQL語(yǔ)句,一條是插入到TableMany表中,第二條是UPDATE TableMany表中的外鍵使得其指向TableOne中的theOne記錄。其實(shí)道理也很簡(jiǎn)單,如果“是否是鏡像”為否,則由One方自己控制,它能控制的方法就是UPDATE TableMany表了,所以就2條SQL語(yǔ)句了。由此也可以推出若One方的<set>標(biāo)簽中若設(shè)置了inverse=true,代碼片斷中的第7行也可以不需要了。
4、實(shí)體類間組合關(guān)系
組合關(guān)系在UML中用實(shí)心的菱形表示,意思是同生共死。那么在NHibernate中就應(yīng)該在父方加上cascade="all-delete-orphan"如下代碼所示:
1<set?
2????name="orders"?
3????cascade="all-delete-orphan"?
4????inverse=true>
5????<key?column="CustomerId"?/>
6????<one-to-many?class="Order"?/>
7</set>
這樣設(shè)置后NHibernate會(huì)幫助完成以下3件事情:
1、級(jí)聯(lián)保存或更新,相當(dāng)于cascade屬性設(shè)置了"save-update"的情況。
2、級(jí)聯(lián)刪除,相當(dāng)于cascade屬性設(shè)置了"delete"的情況。
3、刪除沒(méi)有父的所有子對(duì)象。
5、類圖中是2個(gè)類,但存儲(chǔ)使用一個(gè)表
這種情況很多,比如一個(gè)系統(tǒng)中有用戶和地址,在類圖中應(yīng)該是2個(gè)類會(huì)比較清晰,但是有時(shí)確希望在數(shù)據(jù)庫(kù)中存放在1個(gè)表中,這時(shí)候可以用<component />標(biāo)記,如下所示:
?2????<id?name="Id">
?3????????<generator?class="native"/>
?4????</id>
?5????<property?name="FirstName"/>
?6????<property?name="LastName"/>
?7????<component?name="Component"?class="UserSettings">
?8????????<property?name="Address1"/>
?9????????<property?name="Address2"/>
10????????<property?name="Street"/>
11????????<property?name="State"/>
12????????<property?name="Country"/>
13????</component>
14</class>
6、繼承關(guān)系的幾種映射方法
繼承關(guān)系的映射可以有3種方法:每個(gè)具體類映射一張表、全部映射成一張表、每個(gè)類映射一張表(包括抽象類),下面是實(shí)例,有一個(gè)基類:Animal,二個(gè)子類:Dog、Cat。
每個(gè)具體類映射一張表:
?2????<id?name="Id">
?3????????<generator?class="native"/>
?4????</id>
?5????<property?name="Name"/>
?6</class>
?7
?8<class?name="Cat">
?9????<id?name="Id">
10????????<generator?class="native"/>
11????</id>
12????<property?name="Name"/>
13</class>
這種方式實(shí)際上是沒(méi)有繼承,不能使用以下查詢語(yǔ)句:
1List?Animals?=?session.find("from?Animal");
全部映射一張表:
?2????<id?name="Id">
?3????????<generator?class="native"/>
?4????</id>
?5????<discriminator?column="Type"?type="string"?/>
?6????<property?name="Name"/>
?7
?8????<subclass?name="Dog"?discriminator-value="D">
?9????</subclass>
10
11????<subclass?name="Cat"?discriminator-value="C">
12????</subclass>
13
14</class>
每個(gè)類一個(gè)表(包括抽象類):
?2????<id?name="Id">
?3????????<generator?class="native"/>
?4????</id>
?5????<discriminator?column="Type"?type="string"?/>
?6????<property?name="Name"/>
?7
?8????<joined-subclass?name="Dog">
?9????????<key?column="DogId"?/>
10????</joined-subclass>
11
12????<joined-subclass?name="Cat">
13????????<key?column="CatId"?/>
14????</joined-subclass>
15</class>
7、如何告知hbm2DDL,我要生成ntext屬性?
type="StringClob"是不管用得,應(yīng)該是type="String" 然后設(shè)置一個(gè)大于4000的值給length,如length=5000,即可。
轉(zhuǎn)載于:https://www.cnblogs.com/ron2k/archive/2005/08/16/215686.html
總結(jié)
以上是生活随笔為你收集整理的NHibernate的关键点精要的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 什么是跨域(定义理解错误)
- 下一篇: Vue入门 ---- vuex