黃錫剛
摘要:該文討論的是在傳統(tǒng)中間件環(huán)境下,在數(shù)據(jù)庫多層訪問模型的基礎(chǔ)上,利用對象/關(guān)系映射如何實現(xiàn)對象持久性設(shè)計方案。
關(guān)鍵詞:持久性對象;關(guān)系數(shù)據(jù)庫;三層模型;對象標(biāo)識
中圖分類號:TP393 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2014)14-3285-03
持久對象需解決內(nèi)存中瞬時對象與其他存儲設(shè)備上持久對象的數(shù)據(jù)格式轉(zhuǎn)換問題。主要的存儲設(shè)備有以下的三種:
1)文件系統(tǒng)??梢酝ㄟ^串行化對象來將對象保存在一個文件中。當(dāng)應(yīng)用程序設(shè)計中要求使用文件系統(tǒng)作為持久性基礎(chǔ)設(shè)施來實現(xiàn)應(yīng)用程序中相關(guān)對象的持久性時,我們可以自定義一個文本文件的格式,將對象的狀態(tài)存儲在該文件中。
2)對象數(shù)據(jù)庫。這是保證對象持久性的最合理的做法。但大多數(shù)公司還只是剛開始研究對象數(shù)據(jù)庫,所以還不是主流的存儲介質(zhì)。
3)關(guān)系數(shù)據(jù)庫。目前大多數(shù)先進(jìn)的應(yīng)用程序都使用面向?qū)ο蟮臄?shù)據(jù)結(jié)構(gòu)。但在企業(yè)級的應(yīng)用中大部分的數(shù)據(jù)庫系統(tǒng)仍然是關(guān)系型數(shù)據(jù)庫。雖然面向?qū)ο蟮臄?shù)據(jù)結(jié)構(gòu)對很多應(yīng)用必不可少,但我們?nèi)匀灰紤]很多原有系統(tǒng)的需要,所以關(guān)系數(shù)據(jù)庫的應(yīng)用還是主流。
持久性一般可以分成兩類:空間上的持久性和時間上的持久性。空間上的持久性是在網(wǎng)絡(luò)中傳遞對象的狀態(tài),例如:遠(yuǎn)程方法調(diào)用RMI(Remote Method Invocation, RMI是java分布式對象(EJB)的通信基礎(chǔ)設(shè)施)將對象狀態(tài)串行化后,通過socket傳輸串行化結(jié)果。時間上的持久性中,輕量型持久對象通常保存在本地文件系統(tǒng)中;重量型持久性對象通常采用:O/R映射(關(guān)系/對象映射)+RDB(關(guān)系數(shù)據(jù)庫)來解決。
最簡單的持久性實現(xiàn)方案是在應(yīng)用程序啟動時從文件裝入相關(guān)對象的狀態(tài),在程序結(jié)束時將相關(guān)對象的狀態(tài)存到該文件中。但當(dāng)我們要采用可擴(kuò)展性更好的持久性方案時,譬如實現(xiàn)對象瞬時(transient)狀態(tài)的更新與其持久性是同步的的時候,O/R+RDB的解決辦法就顯得非常實用了。
1 關(guān)系數(shù)據(jù)庫的應(yīng)用
企業(yè)級的應(yīng)用大多數(shù)都采用三層模型來使用中間件訪問數(shù)據(jù)。典型的三層模型由上到下分別是:表示層、業(yè)務(wù)邏輯層、數(shù)據(jù)層。三層結(jié)構(gòu)將業(yè)務(wù)邏輯抽取出來作為一個獨(dú)立的中間層。業(yè)務(wù)邏輯層是對企業(yè)所有業(yè)務(wù)邏輯的一種抽象,對上:為表示層提供了更高級的API;對下:封裝了整個數(shù)據(jù)層。企業(yè)級的應(yīng)用還可以是以三層結(jié)構(gòu)為基礎(chǔ)的擴(kuò)展,例如:在業(yè)務(wù)邏輯層與數(shù)據(jù)層之間引入一層“持久對象層”,持久對象層可以實現(xiàn)對象/關(guān)系映射,數(shù)據(jù)類型轉(zhuǎn)換等功能。
數(shù)據(jù)庫是企業(yè)級應(yīng)用的基礎(chǔ)設(shè)施。在開發(fā)數(shù)據(jù)庫應(yīng)用系統(tǒng)時,引入對象-關(guān)系映射中間件是提高開發(fā)效率、提升軟件可維護(hù)、擴(kuò)展性的需要。成熟的對象-關(guān)系映射中間件產(chǎn)品,可以把內(nèi)存中的對象持久化到數(shù)據(jù)庫中,但前提是我們必須設(shè)計好自己的持久性對象、合理的對象持久性方案。持久性保存數(shù)據(jù)到一個數(shù)據(jù)庫需要注意的是盡量的保持對象持久性的高度透明化。理由有以下4點(diǎn):1) 企業(yè)應(yīng)用需要實現(xiàn)持久性對象,例如:客戶、供應(yīng)商、貨品、訂單等資料都需要持久性的保存到數(shù)據(jù)庫中。2) 代表業(yè)務(wù)邏輯的對象可獨(dú)立于使用它們的程序而存在。3) 多個應(yīng)用程序可能需要工作在同一個對象上。4) 當(dāng)對象與另一個對象交流時,不必了解該對象在內(nèi)存還是在外存。
2 O/R映射基本規(guī)則
對象范式與關(guān)系范式之間存在阻抗不匹配問題,利用已有的O/R映射模式可幫助設(shè)計人員避免實現(xiàn)對象持久性的陷入誤區(qū)?;镜挠成湟?guī)則有以下的三點(diǎn):
1)將屬性影射為列。并不是所有屬性都是持久性的。通常,依賴屬性都不是持久性的。例如:記帳憑證中的借、貸合計。
2)將類映射為表。形式可以是多個類映射到單張表、單張表映射到多張表。多個類映射到同一張表這種情況是由于對象范式含有數(shù)據(jù)與操作,關(guān)系范式僅有數(shù)據(jù),所有O/R映射丟失操作后,某些數(shù)據(jù)可能更適合合并。一個類映射到多張表,這種情況一般是由于要考慮程序效率才這樣做。在某些情況下劃分多張表會提高性能,但如果執(zhí)行涉及連接的操作則通常反而降低性能。
3)類間關(guān)系(繼承、聚集、關(guān)聯(lián))的映射。繼承關(guān)系的映射,一般有三種形式:①整個類層次使用一張表,類層次中所有類的所有屬性均存放在該表中。②每個葉結(jié)點(diǎn)類使用一張表。③每個類使用一張表,該表只保存OID(對象標(biāo)識)以及對應(yīng)類自己的屬性(不含所繼承的屬性)。關(guān)聯(lián)與聚類關(guān)系的映射從關(guān)系范式的角度來看,區(qū)別僅在于耦合程度不同而已。聚類耦合程度高:通常對“整體”操作都伴隨著對“部分”。關(guān)聯(lián)則不存在這么高的相關(guān)度。
3 對象持久性的設(shè)計方案
為了將設(shè)計階段的工作過程清晰的表達(dá)出來,該文簡單的設(shè)計一個餐館訂餐小系統(tǒng)來說明整個設(shè)計過程。
第一步:標(biāo)志那些數(shù)據(jù)需要持久性。
對象標(biāo)識(OID)唯一標(biāo)識關(guān)聯(lián)對象/關(guān)系,在關(guān)系范式里該標(biāo)識稱為關(guān)鍵碼(key),在對象范式里就是作為持久對象標(biāo)識。OID的實現(xiàn)既可以是一個輕量級對象,也可以是整數(shù)、字符串等。OID設(shè)計的基本要求是唯一性和不變性。OID有3種層次的唯一性:1。在同一個類中具有唯一性。2。在同一個類層次中具有唯一性。3,在所有對象中均有唯一性。唯一性范圍越大,則通常的開銷也越大。例如:需要更長的計算機(jī)時間以獲取OID,需要更多的存儲空間以存放OID。OID的不變性是我們?nèi)菀缀雎缘囊粋€重要特征,因為任何業(yè)務(wù)邏輯含義都會發(fā)生變化,從而,任何對象標(biāo)識不應(yīng)含有任何業(yè)務(wù)邏輯含義。
在UML中類是作為指派持久性的基本單位。因為并不是每一個類都需要持久性,所以在設(shè)計過程中用帶標(biāo)簽的值來標(biāo)志持久性,可以采用(名字、值)簡寫的方式來表示,名字為類名,值分別記為Persistent(持久的)和transitory(暫時的),其中默認(rèn)情況下是transitory(如下圖所示)。這一步的設(shè)計我們要注意的是兩個持久類之間的關(guān)聯(lián)也是持久的。
第二步:設(shè)計合適的數(shù)據(jù)庫模式。
在數(shù)據(jù)庫設(shè)計階段,簡單的設(shè)計4張表:Table(桌子) 、Customer(顧客)、Walkin(無預(yù)訂散客)、Reservation(預(yù)約)。每一張表添加顯式的對象標(biāo)識(OID),實現(xiàn)鏈接時用這些對象標(biāo)識作為外碼(FK)。由于本文所設(shè)計的Booking類是一個抽象類,可以簡單地將其具體之類映射為表。餐館訂餐小系統(tǒng)數(shù)據(jù)庫模式設(shè)計結(jié)果為:
第三步:解決對象與關(guān)系的同步問題
這時要解決的問題是:哪一個對象的職責(zé)應(yīng)包含往數(shù)據(jù)庫存放或從數(shù)據(jù)庫裝入對象的功能?因為指派為已有的類會導(dǎo)致聚合性降低,所以引入一個新的類專門執(zhí)行該職責(zé)。為每一持久類定義一個映射類(Mapper)。在設(shè)計模型中引入對象標(biāo)識,從而在領(lǐng)域模型之外亦可實現(xiàn)持久性。為每一持久性類定義子類,在子類中添加對象標(biāo)識。Mapper類處理具有持久性的子類。
第四步:持久性體系結(jié)構(gòu)設(shè)計
Persistent子類和Mapper類依賴于它們所支持的類。它們應(yīng)出現(xiàn)在業(yè)務(wù)邏輯層,但Restaurant類依賴于 Mapper類。將業(yè)務(wù)邏輯層劃分為兩個子包。從而盡量避免了子程序包Persistency的變化對子程序包Domain帶來的影響。持久性體系結(jié)構(gòu)圖如圖4。
4 結(jié)束語
實現(xiàn)重量型持久性對象本文推薦的解決方案是O/R+RDB。持久性對象的設(shè)計的過程為:1)標(biāo)識哪些數(shù)據(jù)需要持久性;2)設(shè)計一個合適的數(shù)據(jù)庫模式;3)解決對象與關(guān)系的同步問題,最后總結(jié)自己的持久性體系結(jié)構(gòu)。該文所描述的持久性對象的設(shè)計過程可以為解決同類問題的提供參考。
參考文獻(xiàn):
[1] 宋波,劉杰,杜慶東.UML面向?qū)ο蠹夹g(shù)與實踐[M].北京:科學(xué)出版社,2005.
[2] 理查德森. Java高級編程:Jdk5[M].沈文炎,譯.北京:機(jī)械工業(yè)出版社,2006.
[3] 霍頓.Java2入門經(jīng)典:JDK5[M].潘曉雷,譯.北京:機(jī)械工業(yè)出版社,2006.endprint
摘要:該文討論的是在傳統(tǒng)中間件環(huán)境下,在數(shù)據(jù)庫多層訪問模型的基礎(chǔ)上,利用對象/關(guān)系映射如何實現(xiàn)對象持久性設(shè)計方案。
關(guān)鍵詞:持久性對象;關(guān)系數(shù)據(jù)庫;三層模型;對象標(biāo)識
中圖分類號:TP393 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2014)14-3285-03
持久對象需解決內(nèi)存中瞬時對象與其他存儲設(shè)備上持久對象的數(shù)據(jù)格式轉(zhuǎn)換問題。主要的存儲設(shè)備有以下的三種:
1)文件系統(tǒng)??梢酝ㄟ^串行化對象來將對象保存在一個文件中。當(dāng)應(yīng)用程序設(shè)計中要求使用文件系統(tǒng)作為持久性基礎(chǔ)設(shè)施來實現(xiàn)應(yīng)用程序中相關(guān)對象的持久性時,我們可以自定義一個文本文件的格式,將對象的狀態(tài)存儲在該文件中。
2)對象數(shù)據(jù)庫。這是保證對象持久性的最合理的做法。但大多數(shù)公司還只是剛開始研究對象數(shù)據(jù)庫,所以還不是主流的存儲介質(zhì)。
3)關(guān)系數(shù)據(jù)庫。目前大多數(shù)先進(jìn)的應(yīng)用程序都使用面向?qū)ο蟮臄?shù)據(jù)結(jié)構(gòu)。但在企業(yè)級的應(yīng)用中大部分的數(shù)據(jù)庫系統(tǒng)仍然是關(guān)系型數(shù)據(jù)庫。雖然面向?qū)ο蟮臄?shù)據(jù)結(jié)構(gòu)對很多應(yīng)用必不可少,但我們?nèi)匀灰紤]很多原有系統(tǒng)的需要,所以關(guān)系數(shù)據(jù)庫的應(yīng)用還是主流。
持久性一般可以分成兩類:空間上的持久性和時間上的持久性。空間上的持久性是在網(wǎng)絡(luò)中傳遞對象的狀態(tài),例如:遠(yuǎn)程方法調(diào)用RMI(Remote Method Invocation, RMI是java分布式對象(EJB)的通信基礎(chǔ)設(shè)施)將對象狀態(tài)串行化后,通過socket傳輸串行化結(jié)果。時間上的持久性中,輕量型持久對象通常保存在本地文件系統(tǒng)中;重量型持久性對象通常采用:O/R映射(關(guān)系/對象映射)+RDB(關(guān)系數(shù)據(jù)庫)來解決。
最簡單的持久性實現(xiàn)方案是在應(yīng)用程序啟動時從文件裝入相關(guān)對象的狀態(tài),在程序結(jié)束時將相關(guān)對象的狀態(tài)存到該文件中。但當(dāng)我們要采用可擴(kuò)展性更好的持久性方案時,譬如實現(xiàn)對象瞬時(transient)狀態(tài)的更新與其持久性是同步的的時候,O/R+RDB的解決辦法就顯得非常實用了。
1 關(guān)系數(shù)據(jù)庫的應(yīng)用
企業(yè)級的應(yīng)用大多數(shù)都采用三層模型來使用中間件訪問數(shù)據(jù)。典型的三層模型由上到下分別是:表示層、業(yè)務(wù)邏輯層、數(shù)據(jù)層。三層結(jié)構(gòu)將業(yè)務(wù)邏輯抽取出來作為一個獨(dú)立的中間層。業(yè)務(wù)邏輯層是對企業(yè)所有業(yè)務(wù)邏輯的一種抽象,對上:為表示層提供了更高級的API;對下:封裝了整個數(shù)據(jù)層。企業(yè)級的應(yīng)用還可以是以三層結(jié)構(gòu)為基礎(chǔ)的擴(kuò)展,例如:在業(yè)務(wù)邏輯層與數(shù)據(jù)層之間引入一層“持久對象層”,持久對象層可以實現(xiàn)對象/關(guān)系映射,數(shù)據(jù)類型轉(zhuǎn)換等功能。
數(shù)據(jù)庫是企業(yè)級應(yīng)用的基礎(chǔ)設(shè)施。在開發(fā)數(shù)據(jù)庫應(yīng)用系統(tǒng)時,引入對象-關(guān)系映射中間件是提高開發(fā)效率、提升軟件可維護(hù)、擴(kuò)展性的需要。成熟的對象-關(guān)系映射中間件產(chǎn)品,可以把內(nèi)存中的對象持久化到數(shù)據(jù)庫中,但前提是我們必須設(shè)計好自己的持久性對象、合理的對象持久性方案。持久性保存數(shù)據(jù)到一個數(shù)據(jù)庫需要注意的是盡量的保持對象持久性的高度透明化。理由有以下4點(diǎn):1) 企業(yè)應(yīng)用需要實現(xiàn)持久性對象,例如:客戶、供應(yīng)商、貨品、訂單等資料都需要持久性的保存到數(shù)據(jù)庫中。2) 代表業(yè)務(wù)邏輯的對象可獨(dú)立于使用它們的程序而存在。3) 多個應(yīng)用程序可能需要工作在同一個對象上。4) 當(dāng)對象與另一個對象交流時,不必了解該對象在內(nèi)存還是在外存。
2 O/R映射基本規(guī)則
對象范式與關(guān)系范式之間存在阻抗不匹配問題,利用已有的O/R映射模式可幫助設(shè)計人員避免實現(xiàn)對象持久性的陷入誤區(qū)。基本的映射規(guī)則有以下的三點(diǎn):
1)將屬性影射為列。并不是所有屬性都是持久性的。通常,依賴屬性都不是持久性的。例如:記帳憑證中的借、貸合計。
2)將類映射為表。形式可以是多個類映射到單張表、單張表映射到多張表。多個類映射到同一張表這種情況是由于對象范式含有數(shù)據(jù)與操作,關(guān)系范式僅有數(shù)據(jù),所有O/R映射丟失操作后,某些數(shù)據(jù)可能更適合合并。一個類映射到多張表,這種情況一般是由于要考慮程序效率才這樣做。在某些情況下劃分多張表會提高性能,但如果執(zhí)行涉及連接的操作則通常反而降低性能。
3)類間關(guān)系(繼承、聚集、關(guān)聯(lián))的映射。繼承關(guān)系的映射,一般有三種形式:①整個類層次使用一張表,類層次中所有類的所有屬性均存放在該表中。②每個葉結(jié)點(diǎn)類使用一張表。③每個類使用一張表,該表只保存OID(對象標(biāo)識)以及對應(yīng)類自己的屬性(不含所繼承的屬性)。關(guān)聯(lián)與聚類關(guān)系的映射從關(guān)系范式的角度來看,區(qū)別僅在于耦合程度不同而已。聚類耦合程度高:通常對“整體”操作都伴隨著對“部分”。關(guān)聯(lián)則不存在這么高的相關(guān)度。
3 對象持久性的設(shè)計方案
為了將設(shè)計階段的工作過程清晰的表達(dá)出來,該文簡單的設(shè)計一個餐館訂餐小系統(tǒng)來說明整個設(shè)計過程。
第一步:標(biāo)志那些數(shù)據(jù)需要持久性。
對象標(biāo)識(OID)唯一標(biāo)識關(guān)聯(lián)對象/關(guān)系,在關(guān)系范式里該標(biāo)識稱為關(guān)鍵碼(key),在對象范式里就是作為持久對象標(biāo)識。OID的實現(xiàn)既可以是一個輕量級對象,也可以是整數(shù)、字符串等。OID設(shè)計的基本要求是唯一性和不變性。OID有3種層次的唯一性:1。在同一個類中具有唯一性。2。在同一個類層次中具有唯一性。3,在所有對象中均有唯一性。唯一性范圍越大,則通常的開銷也越大。例如:需要更長的計算機(jī)時間以獲取OID,需要更多的存儲空間以存放OID。OID的不變性是我們?nèi)菀缀雎缘囊粋€重要特征,因為任何業(yè)務(wù)邏輯含義都會發(fā)生變化,從而,任何對象標(biāo)識不應(yīng)含有任何業(yè)務(wù)邏輯含義。
在UML中類是作為指派持久性的基本單位。因為并不是每一個類都需要持久性,所以在設(shè)計過程中用帶標(biāo)簽的值來標(biāo)志持久性,可以采用(名字、值)簡寫的方式來表示,名字為類名,值分別記為Persistent(持久的)和transitory(暫時的),其中默認(rèn)情況下是transitory(如下圖所示)。這一步的設(shè)計我們要注意的是兩個持久類之間的關(guān)聯(lián)也是持久的。
第二步:設(shè)計合適的數(shù)據(jù)庫模式。
在數(shù)據(jù)庫設(shè)計階段,簡單的設(shè)計4張表:Table(桌子) 、Customer(顧客)、Walkin(無預(yù)訂散客)、Reservation(預(yù)約)。每一張表添加顯式的對象標(biāo)識(OID),實現(xiàn)鏈接時用這些對象標(biāo)識作為外碼(FK)。由于本文所設(shè)計的Booking類是一個抽象類,可以簡單地將其具體之類映射為表。餐館訂餐小系統(tǒng)數(shù)據(jù)庫模式設(shè)計結(jié)果為:
第三步:解決對象與關(guān)系的同步問題
這時要解決的問題是:哪一個對象的職責(zé)應(yīng)包含往數(shù)據(jù)庫存放或從數(shù)據(jù)庫裝入對象的功能?因為指派為已有的類會導(dǎo)致聚合性降低,所以引入一個新的類專門執(zhí)行該職責(zé)。為每一持久類定義一個映射類(Mapper)。在設(shè)計模型中引入對象標(biāo)識,從而在領(lǐng)域模型之外亦可實現(xiàn)持久性。為每一持久性類定義子類,在子類中添加對象標(biāo)識。Mapper類處理具有持久性的子類。
第四步:持久性體系結(jié)構(gòu)設(shè)計
Persistent子類和Mapper類依賴于它們所支持的類。它們應(yīng)出現(xiàn)在業(yè)務(wù)邏輯層,但Restaurant類依賴于 Mapper類。將業(yè)務(wù)邏輯層劃分為兩個子包。從而盡量避免了子程序包Persistency的變化對子程序包Domain帶來的影響。持久性體系結(jié)構(gòu)圖如圖4。
4 結(jié)束語
實現(xiàn)重量型持久性對象本文推薦的解決方案是O/R+RDB。持久性對象的設(shè)計的過程為:1)標(biāo)識哪些數(shù)據(jù)需要持久性;2)設(shè)計一個合適的數(shù)據(jù)庫模式;3)解決對象與關(guān)系的同步問題,最后總結(jié)自己的持久性體系結(jié)構(gòu)。該文所描述的持久性對象的設(shè)計過程可以為解決同類問題的提供參考。
參考文獻(xiàn):
[1] 宋波,劉杰,杜慶東.UML面向?qū)ο蠹夹g(shù)與實踐[M].北京:科學(xué)出版社,2005.
[2] 理查德森. Java高級編程:Jdk5[M].沈文炎,譯.北京:機(jī)械工業(yè)出版社,2006.
[3] 霍頓.Java2入門經(jīng)典:JDK5[M].潘曉雷,譯.北京:機(jī)械工業(yè)出版社,2006.endprint
摘要:該文討論的是在傳統(tǒng)中間件環(huán)境下,在數(shù)據(jù)庫多層訪問模型的基礎(chǔ)上,利用對象/關(guān)系映射如何實現(xiàn)對象持久性設(shè)計方案。
關(guān)鍵詞:持久性對象;關(guān)系數(shù)據(jù)庫;三層模型;對象標(biāo)識
中圖分類號:TP393 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2014)14-3285-03
持久對象需解決內(nèi)存中瞬時對象與其他存儲設(shè)備上持久對象的數(shù)據(jù)格式轉(zhuǎn)換問題。主要的存儲設(shè)備有以下的三種:
1)文件系統(tǒng)??梢酝ㄟ^串行化對象來將對象保存在一個文件中。當(dāng)應(yīng)用程序設(shè)計中要求使用文件系統(tǒng)作為持久性基礎(chǔ)設(shè)施來實現(xiàn)應(yīng)用程序中相關(guān)對象的持久性時,我們可以自定義一個文本文件的格式,將對象的狀態(tài)存儲在該文件中。
2)對象數(shù)據(jù)庫。這是保證對象持久性的最合理的做法。但大多數(shù)公司還只是剛開始研究對象數(shù)據(jù)庫,所以還不是主流的存儲介質(zhì)。
3)關(guān)系數(shù)據(jù)庫。目前大多數(shù)先進(jìn)的應(yīng)用程序都使用面向?qū)ο蟮臄?shù)據(jù)結(jié)構(gòu)。但在企業(yè)級的應(yīng)用中大部分的數(shù)據(jù)庫系統(tǒng)仍然是關(guān)系型數(shù)據(jù)庫。雖然面向?qū)ο蟮臄?shù)據(jù)結(jié)構(gòu)對很多應(yīng)用必不可少,但我們?nèi)匀灰紤]很多原有系統(tǒng)的需要,所以關(guān)系數(shù)據(jù)庫的應(yīng)用還是主流。
持久性一般可以分成兩類:空間上的持久性和時間上的持久性??臻g上的持久性是在網(wǎng)絡(luò)中傳遞對象的狀態(tài),例如:遠(yuǎn)程方法調(diào)用RMI(Remote Method Invocation, RMI是java分布式對象(EJB)的通信基礎(chǔ)設(shè)施)將對象狀態(tài)串行化后,通過socket傳輸串行化結(jié)果。時間上的持久性中,輕量型持久對象通常保存在本地文件系統(tǒng)中;重量型持久性對象通常采用:O/R映射(關(guān)系/對象映射)+RDB(關(guān)系數(shù)據(jù)庫)來解決。
最簡單的持久性實現(xiàn)方案是在應(yīng)用程序啟動時從文件裝入相關(guān)對象的狀態(tài),在程序結(jié)束時將相關(guān)對象的狀態(tài)存到該文件中。但當(dāng)我們要采用可擴(kuò)展性更好的持久性方案時,譬如實現(xiàn)對象瞬時(transient)狀態(tài)的更新與其持久性是同步的的時候,O/R+RDB的解決辦法就顯得非常實用了。
1 關(guān)系數(shù)據(jù)庫的應(yīng)用
企業(yè)級的應(yīng)用大多數(shù)都采用三層模型來使用中間件訪問數(shù)據(jù)。典型的三層模型由上到下分別是:表示層、業(yè)務(wù)邏輯層、數(shù)據(jù)層。三層結(jié)構(gòu)將業(yè)務(wù)邏輯抽取出來作為一個獨(dú)立的中間層。業(yè)務(wù)邏輯層是對企業(yè)所有業(yè)務(wù)邏輯的一種抽象,對上:為表示層提供了更高級的API;對下:封裝了整個數(shù)據(jù)層。企業(yè)級的應(yīng)用還可以是以三層結(jié)構(gòu)為基礎(chǔ)的擴(kuò)展,例如:在業(yè)務(wù)邏輯層與數(shù)據(jù)層之間引入一層“持久對象層”,持久對象層可以實現(xiàn)對象/關(guān)系映射,數(shù)據(jù)類型轉(zhuǎn)換等功能。
數(shù)據(jù)庫是企業(yè)級應(yīng)用的基礎(chǔ)設(shè)施。在開發(fā)數(shù)據(jù)庫應(yīng)用系統(tǒng)時,引入對象-關(guān)系映射中間件是提高開發(fā)效率、提升軟件可維護(hù)、擴(kuò)展性的需要。成熟的對象-關(guān)系映射中間件產(chǎn)品,可以把內(nèi)存中的對象持久化到數(shù)據(jù)庫中,但前提是我們必須設(shè)計好自己的持久性對象、合理的對象持久性方案。持久性保存數(shù)據(jù)到一個數(shù)據(jù)庫需要注意的是盡量的保持對象持久性的高度透明化。理由有以下4點(diǎn):1) 企業(yè)應(yīng)用需要實現(xiàn)持久性對象,例如:客戶、供應(yīng)商、貨品、訂單等資料都需要持久性的保存到數(shù)據(jù)庫中。2) 代表業(yè)務(wù)邏輯的對象可獨(dú)立于使用它們的程序而存在。3) 多個應(yīng)用程序可能需要工作在同一個對象上。4) 當(dāng)對象與另一個對象交流時,不必了解該對象在內(nèi)存還是在外存。
2 O/R映射基本規(guī)則
對象范式與關(guān)系范式之間存在阻抗不匹配問題,利用已有的O/R映射模式可幫助設(shè)計人員避免實現(xiàn)對象持久性的陷入誤區(qū)?;镜挠成湟?guī)則有以下的三點(diǎn):
1)將屬性影射為列。并不是所有屬性都是持久性的。通常,依賴屬性都不是持久性的。例如:記帳憑證中的借、貸合計。
2)將類映射為表。形式可以是多個類映射到單張表、單張表映射到多張表。多個類映射到同一張表這種情況是由于對象范式含有數(shù)據(jù)與操作,關(guān)系范式僅有數(shù)據(jù),所有O/R映射丟失操作后,某些數(shù)據(jù)可能更適合合并。一個類映射到多張表,這種情況一般是由于要考慮程序效率才這樣做。在某些情況下劃分多張表會提高性能,但如果執(zhí)行涉及連接的操作則通常反而降低性能。
3)類間關(guān)系(繼承、聚集、關(guān)聯(lián))的映射。繼承關(guān)系的映射,一般有三種形式:①整個類層次使用一張表,類層次中所有類的所有屬性均存放在該表中。②每個葉結(jié)點(diǎn)類使用一張表。③每個類使用一張表,該表只保存OID(對象標(biāo)識)以及對應(yīng)類自己的屬性(不含所繼承的屬性)。關(guān)聯(lián)與聚類關(guān)系的映射從關(guān)系范式的角度來看,區(qū)別僅在于耦合程度不同而已。聚類耦合程度高:通常對“整體”操作都伴隨著對“部分”。關(guān)聯(lián)則不存在這么高的相關(guān)度。
3 對象持久性的設(shè)計方案
為了將設(shè)計階段的工作過程清晰的表達(dá)出來,該文簡單的設(shè)計一個餐館訂餐小系統(tǒng)來說明整個設(shè)計過程。
第一步:標(biāo)志那些數(shù)據(jù)需要持久性。
對象標(biāo)識(OID)唯一標(biāo)識關(guān)聯(lián)對象/關(guān)系,在關(guān)系范式里該標(biāo)識稱為關(guān)鍵碼(key),在對象范式里就是作為持久對象標(biāo)識。OID的實現(xiàn)既可以是一個輕量級對象,也可以是整數(shù)、字符串等。OID設(shè)計的基本要求是唯一性和不變性。OID有3種層次的唯一性:1。在同一個類中具有唯一性。2。在同一個類層次中具有唯一性。3,在所有對象中均有唯一性。唯一性范圍越大,則通常的開銷也越大。例如:需要更長的計算機(jī)時間以獲取OID,需要更多的存儲空間以存放OID。OID的不變性是我們?nèi)菀缀雎缘囊粋€重要特征,因為任何業(yè)務(wù)邏輯含義都會發(fā)生變化,從而,任何對象標(biāo)識不應(yīng)含有任何業(yè)務(wù)邏輯含義。
在UML中類是作為指派持久性的基本單位。因為并不是每一個類都需要持久性,所以在設(shè)計過程中用帶標(biāo)簽的值來標(biāo)志持久性,可以采用(名字、值)簡寫的方式來表示,名字為類名,值分別記為Persistent(持久的)和transitory(暫時的),其中默認(rèn)情況下是transitory(如下圖所示)。這一步的設(shè)計我們要注意的是兩個持久類之間的關(guān)聯(lián)也是持久的。
第二步:設(shè)計合適的數(shù)據(jù)庫模式。
在數(shù)據(jù)庫設(shè)計階段,簡單的設(shè)計4張表:Table(桌子) 、Customer(顧客)、Walkin(無預(yù)訂散客)、Reservation(預(yù)約)。每一張表添加顯式的對象標(biāo)識(OID),實現(xiàn)鏈接時用這些對象標(biāo)識作為外碼(FK)。由于本文所設(shè)計的Booking類是一個抽象類,可以簡單地將其具體之類映射為表。餐館訂餐小系統(tǒng)數(shù)據(jù)庫模式設(shè)計結(jié)果為:
第三步:解決對象與關(guān)系的同步問題
這時要解決的問題是:哪一個對象的職責(zé)應(yīng)包含往數(shù)據(jù)庫存放或從數(shù)據(jù)庫裝入對象的功能?因為指派為已有的類會導(dǎo)致聚合性降低,所以引入一個新的類專門執(zhí)行該職責(zé)。為每一持久類定義一個映射類(Mapper)。在設(shè)計模型中引入對象標(biāo)識,從而在領(lǐng)域模型之外亦可實現(xiàn)持久性。為每一持久性類定義子類,在子類中添加對象標(biāo)識。Mapper類處理具有持久性的子類。
第四步:持久性體系結(jié)構(gòu)設(shè)計
Persistent子類和Mapper類依賴于它們所支持的類。它們應(yīng)出現(xiàn)在業(yè)務(wù)邏輯層,但Restaurant類依賴于 Mapper類。將業(yè)務(wù)邏輯層劃分為兩個子包。從而盡量避免了子程序包Persistency的變化對子程序包Domain帶來的影響。持久性體系結(jié)構(gòu)圖如圖4。
4 結(jié)束語
實現(xiàn)重量型持久性對象本文推薦的解決方案是O/R+RDB。持久性對象的設(shè)計的過程為:1)標(biāo)識哪些數(shù)據(jù)需要持久性;2)設(shè)計一個合適的數(shù)據(jù)庫模式;3)解決對象與關(guān)系的同步問題,最后總結(jié)自己的持久性體系結(jié)構(gòu)。該文所描述的持久性對象的設(shè)計過程可以為解決同類問題的提供參考。
參考文獻(xiàn):
[1] 宋波,劉杰,杜慶東.UML面向?qū)ο蠹夹g(shù)與實踐[M].北京:科學(xué)出版社,2005.
[2] 理查德森. Java高級編程:Jdk5[M].沈文炎,譯.北京:機(jī)械工業(yè)出版社,2006.
[3] 霍頓.Java2入門經(jīng)典:JDK5[M].潘曉雷,譯.北京:機(jī)械工業(yè)出版社,2006.endprint