周微民
(中國電子科技集團公司第二十八研究所 南京 210007)
目前的應用軟件大多通過ODBC、JDBC、ADO、BDE等最原始、最直接的方法訪問數(shù)據(jù)庫,或是通過數(shù)據(jù)庫廠商提供的接口訪問數(shù)據(jù)庫,這些方式雖然運行效率高,但是在程序中嵌入了大量的SQL語句,使得項目難以維護。如果關(guān)系數(shù)據(jù)模型非常復雜,直接寫SQL需要專業(yè)的知識,對于企業(yè)級應用的開發(fā)人員,從頭開發(fā)自己的持久化層是不可行的。同時由于數(shù)據(jù)標準、規(guī)范的建設滯后于信息系統(tǒng)的發(fā)展,各個信息系統(tǒng)中的數(shù)據(jù)庫資源都存在著語義、結(jié)構(gòu)等方面的異構(gòu)性[1],因此需要對象關(guān)系映射層,把數(shù)據(jù)庫訪問操作封裝起來,提供統(tǒng)一的對象接口,供業(yè)務調(diào)用。
對象/關(guān)系映射技術(shù)有多種實現(xiàn),開源項目有 Hibernate[2]、NHibernate[3]、Castle 框 架。Hibernate是 “對 象—關(guān)系映射(Object—Relational Mapping,ORM)模塊實現(xiàn)數(shù)據(jù)持久層的一個優(yōu)秀的Java組件。ORM元素主要功能是實現(xiàn)實體域?qū)ο蟮某志没⒎庋b[4]數(shù)據(jù)訪問的細節(jié)。Hibernate對JDBC進行了非常輕量級的封裝,其對象/關(guān)系數(shù)據(jù)庫映射,持久化,事務管理,緩存機制的功能很好,但是Hibernate在復雜多表聯(lián)合數(shù)據(jù)處理上的能力較弱;對于復雜的多表操作不適合用Hibernate。微軟NHibernate是基于Microsoft.NET的O/R Map2ping持久化框架。它從數(shù)據(jù)庫底層來持久化.Net對象到關(guān)系型數(shù)據(jù)庫。它不僅管理.NET類到數(shù)據(jù)庫表的映射,還提供數(shù)據(jù)查詢和獲取數(shù)據(jù)的方法[5]。但是其中的對象也只是相對比較簡單的主表和幾張子表之間關(guān)聯(lián)的對象,對象間的復雜關(guān)聯(lián)無法體現(xiàn)出來。Castle框架是針對.NET平臺的一個非常優(yōu)秀的開源項目,從數(shù)據(jù)訪問框架ORM(Object2Relational Mapping,對象關(guān)系映射)到IOC(Inversion of Cont rol,控制反轉(zhuǎn)或者叫依賴注入)容器,再到WEB層的MVC框架,基本包括了整個開發(fā)過程中的所有內(nèi)容,為開發(fā)易擴展、可伸縮、靈活、健壯的軟件系統(tǒng)提供了一個很好的平臺[6]。Castle封裝了NHibernate的大部分煩雜細節(jié),不需要像NHibernate那樣去編寫復雜的對象映射文件,配置少且靈活,但是無法支持大型系統(tǒng)復雜的數(shù)據(jù)庫邏輯。
針對上述不足,本文設計了復雜對象模型以及基于該對象模型的數(shù)據(jù)快速訪問方案,采用這種方法進行數(shù)據(jù)庫應用系統(tǒng)開發(fā),將增強系統(tǒng)的數(shù)據(jù)庫訪問能力和對軟件環(huán)境的適應能力,當系統(tǒng)更換底層數(shù)據(jù)庫系統(tǒng),或更改數(shù)據(jù)庫物理表和字段信息時,只需修改對象和數(shù)據(jù)實體的映射關(guān)系,不會對系統(tǒng)產(chǎn)生大的影響。
為了屏蔽數(shù)據(jù)庫,采用持久化技術(shù)。持久化技術(shù)的基本思想是以用面向?qū)ο蟮募夹g(shù)將數(shù)據(jù)庫關(guān)系表以及表中的記錄都看成是可以持久的對象。在這種技術(shù)中,首先可以利用面向?qū)ο蟮乃枷?,“持久化”包括和?shù)據(jù)庫相關(guān)的各種操作,并建立其對象模型。例如,保存:把域?qū)ο笥谰帽4娴綌?shù)據(jù)庫;更新:更新數(shù)據(jù)庫中的域?qū)ο蟮臓顟B(tài);刪除:從數(shù)據(jù)庫中刪除一個域?qū)ο?;加載:根據(jù)特定的OID,把一個域?qū)ο髲臄?shù)據(jù)庫加載到內(nèi)存;查詢:根據(jù)特定的查詢條件,把符合查詢條件的一個或多個域?qū)ο髲臄?shù)據(jù)庫加載到內(nèi)存中[7]。本文根據(jù)持久化思想設計了業(yè)務對象模型。
業(yè)務對象模型是基于元數(shù)據(jù)庫的,元數(shù)據(jù)庫主要用于管理元數(shù)據(jù)。元數(shù)據(jù)是數(shù)據(jù)的組織、數(shù)據(jù)域以及關(guān)系的信息,也就是數(shù)據(jù)的數(shù)據(jù)[8]。元數(shù)據(jù)庫主要存儲了用戶需要訪問數(shù)據(jù)的相關(guān)數(shù)據(jù)對象的描述信息,構(gòu)成數(shù)據(jù)庫邏輯視圖,其中數(shù)據(jù)庫結(jié)構(gòu)信息主要來源于數(shù)據(jù)字典,即數(shù)據(jù)庫中用于存儲數(shù)據(jù)庫對象結(jié)構(gòu)信息的專用表和視圖。
業(yè)務對象主要描述業(yè)務操作的數(shù)據(jù)訪問視圖,以XML的方式展現(xiàn),具體內(nèi)容包括:
1)對象信息:對象類名稱、對象類描述、數(shù)據(jù)庫對象ID、對象狀態(tài)、對象類型;
2)對象關(guān)系映射信息:對象屬性信息、映射的數(shù)據(jù)庫信息;
3)對象關(guān)聯(lián)信息:對象內(nèi)部表間的關(guān)聯(lián)描述、對象間的關(guān)聯(lián)描述;
4)對象操作信息。增刪改查的命名SQL:SQL名稱、SQL描述、SQL中的參數(shù)描述(包括參數(shù)名稱、類型)、SQL的輸出字段別名名稱。級聯(lián)操作描述:在增加、修改、刪除記錄操作之前和之后執(zhí)行的各種命名SQL描述,SQL執(zhí)行順序號。
復雜對象是基于業(yè)務對象的,是簡單業(yè)務對象間的關(guān)聯(lián)關(guān)系組合。簡單業(yè)務對象間的關(guān)聯(lián)關(guān)系包括兩類:
1)如果一個簡單業(yè)務對象A的刪、改、查操作的任一條件字段的值能夠包含在另一個簡單業(yè)務對象B的查詢結(jié)果中,可以認為B與A之間存在父子關(guān)系;
2)如果兩個簡單業(yè)務對象A和A′,都是簡單業(yè)務對象B的子對象,則可以認為A和A′存在兄弟關(guān)系。
對象化數(shù)據(jù)訪問主要由業(yè)務對象和數(shù)據(jù)訪問兩個部分組成。業(yè)務對象根據(jù)實際應用的數(shù)據(jù)需求分為簡單業(yè)務對象和復雜業(yè)務對象,主要存儲對象和數(shù)據(jù)庫表之間的映射關(guān)系;數(shù)據(jù)訪問主要通過動態(tài)加載業(yè)務對象來完成用戶對數(shù)據(jù)庫數(shù)據(jù)的操作。
對象化數(shù)據(jù)訪問的主要工作流程為:先抽取專業(yè)數(shù)據(jù)庫結(jié)構(gòu)到元數(shù)據(jù)庫中,形成數(shù)據(jù)庫邏輯視圖;再利用元數(shù)據(jù)庫生成簡單業(yè)務對象,描述業(yè)務操作的數(shù)據(jù)訪問視圖;然后分析生成的多個簡單業(yè)務對象間的關(guān)聯(lián)關(guān)系,根據(jù)業(yè)務需要設置對象間的關(guān)聯(lián)關(guān)系生成復雜業(yè)務對象,描述業(yè)務流程的數(shù)據(jù)訪問視圖;最后完成對象的數(shù)據(jù)訪問。
2.2.1 業(yè)務對象的生成
業(yè)務對象是依托元數(shù)據(jù)庫的,所以要先構(gòu)建元數(shù)據(jù)庫,然后再生成業(yè)務對象。
1)抽取元數(shù)據(jù)
根據(jù)數(shù)據(jù)模型的描述,從專業(yè)數(shù)據(jù)庫的數(shù)據(jù)字典讀取需要訪問數(shù)據(jù)的相關(guān)數(shù)據(jù)對象(包括數(shù)據(jù)表、字段、約束等)的描述信息,存入元數(shù)據(jù)庫中,為業(yè)務對象的生成提供支持。主要步驟如下:
(1)讀取專業(yè)數(shù)據(jù)庫的連接信息;
(2)讀取專業(yè)數(shù)據(jù)庫里表的描述信息;
(3)讀取專業(yè)數(shù)據(jù)庫里表字段的描述信息;
(4)讀取專業(yè)數(shù)據(jù)庫里表的關(guān)聯(lián)信息;
(5)將專業(yè)數(shù)據(jù)庫的元數(shù)據(jù)描述信息存入元數(shù)據(jù)庫,供生成業(yè)務對象時使用。
該操作需要了解數(shù)據(jù)模型的人員參與選擇數(shù)據(jù)表和其他對象的范圍,需要根據(jù)應用要求增加或修改表的關(guān)聯(lián)關(guān)系或字段的取值范圍等,保存在元數(shù)據(jù)中,供后面生成對象時使用該邏輯關(guān)聯(lián)。對專業(yè)數(shù)據(jù)庫的元數(shù)據(jù)描述包括:
(1)數(shù)據(jù)表信息:表名稱、字段組成、主鍵字段;
(2)字段信息:字段名稱、字段類型、字段長度、是否非空;
(3)關(guān)聯(lián)關(guān)系:主子表的關(guān)聯(lián)信息。
2)生成簡單業(yè)務對象
從元數(shù)據(jù)模型中讀取數(shù)據(jù)表信息及其關(guān)聯(lián)表信息,以人機交互方式供用戶選擇與具體業(yè)務操作相關(guān)的一組表及其關(guān)心字段;根據(jù)用戶選擇的表和字段信息,及其元數(shù)據(jù)描述,自動生成對表間關(guān)聯(lián)關(guān)系、讀取順序的描述,以及默認的級聯(lián)增刪改查操作的SQL語句。允許用戶以人機交互方式修改默認生成的SQL語句,支持SQL的修改、增加、刪除,支持以參數(shù)形式定義SQL查詢條件,保存業(yè)務對象信息到XML中。具體操作流程如圖1所示。
3)生成復雜業(yè)務對象
根據(jù)分析的2.2.1節(jié)中用戶定義的一組簡單業(yè)務對象的關(guān)聯(lián)關(guān)系,生成對象樹??赡艽嬖诙嗫脤ο髽洌桓鶕?jù)對簡單業(yè)務對象樹的深度和廣度兩種遍歷方式,生成供用戶參考的對象訪問操作執(zhí)行順序鏈表。用戶通過人機交互方式確定業(yè)務工作流程中可能存在的一種或多種對象操作的訪問操作執(zhí)行順序,還可以給出選擇某種執(zhí)行順序的條件或優(yōu)先級;與某個工作流程相關(guān)的一組簡單對象,構(gòu)成復雜業(yè)務對象,同樣以XML存儲,XML中包含以下信息:
(1)包含的簡單業(yè)務對象列表,引用位置。
(2)描述簡單業(yè)務對象間的父子關(guān)系或兄弟關(guān)系,描述建立上述關(guān)系的表和字段。
(3)描述簡單對象訪問操作的執(zhí)行順序,及選擇某種執(zhí)行順序的條件或優(yōu)先級。
2.2.2 數(shù)據(jù)訪問
圖1 生成簡單業(yè)務對象的過程
數(shù)據(jù)訪問主要提供數(shù)據(jù)庫中各類對象的數(shù)據(jù)訪問操作、查詢優(yōu)化[9]以及連接池管理。數(shù)據(jù)訪問操作包括查詢、增加、修改和刪除,接口類型為對象類型。查詢優(yōu)化主要包括查詢預取隊列和關(guān)鍵對象緩存:根據(jù)復雜業(yè)務對象描述中對象操作的執(zhí)行順序,抽取執(zhí)行操作序列中的查詢操作,形成查詢預取隊列;在50%以上的復雜業(yè)務對象中存在,且至少存在于兩個復雜業(yè)務對象中的簡單對象稱作關(guān)鍵對象,將關(guān)鍵對象存儲在內(nèi)存中形成關(guān)鍵對象緩存鏈表。連接池管理主要管理數(shù)據(jù)庫的連接,保證數(shù)據(jù)庫資源的合理分配。
根據(jù)應用的對象接口請求執(zhí)行對象的增刪改查操作,具體操作流程如圖2所示。
圖2 對象數(shù)據(jù)訪問及優(yōu)化的流程
1)如果是查詢操作,步驟如下:
(1)如果查詢對象不在緩存中,則從數(shù)據(jù)庫獲取查詢結(jié)果,反射成對象集,如果該對象在關(guān)鍵對象緩存鏈表中,則將對象集數(shù)據(jù)駐留在緩存中;再根據(jù)查詢預取隊列,獲得下一個對象查詢操作,利用空閑時間提前執(zhí)行。
(2)如果查詢對象數(shù)據(jù)已經(jīng)在緩存中,則不訪問數(shù)據(jù)庫,直接從緩存中獲取對象。
(3)然后操作對象本身及其關(guān)聯(lián)的對象。
2)如果是對象的增刪改操作,則根據(jù)復雜對象文件的級聯(lián)配置執(zhí)行級聯(lián)操作,提交數(shù)據(jù)庫。如果未設置級聯(lián)關(guān)系,則執(zhí)行單表操作,提交數(shù)據(jù)庫;如果執(zhí)行增刪改操作的對象是關(guān)鍵對象,則還需根據(jù)增刪改結(jié)果更新緩存中的對象數(shù)據(jù)。
在對象關(guān)系映射系統(tǒng)中,對象預取與緩存技術(shù)可以提高用戶對持久化對象的訪問效率。
通過某種策略預測將來可能會被訪問到的對象,并預先將這些對象讀取到客戶端。如果預測對象在后面確實被訪問到了,那么預取策略會有效的減少數(shù)據(jù)訪問到數(shù)據(jù)庫查詢對象的操作,提高數(shù)據(jù)訪問性能。相反,如果預取對象沒有被訪問到,則會降低系統(tǒng)的性能,所以制定合理的預取策略是至關(guān)重要的。
本方案是通過抽取復雜對象操作序列中的查詢操作形成查詢預取隊列來構(gòu)建預取策略的。在生成復雜對象的過程中,用戶可以使用和修改定制默認生成的簡單對象間關(guān)聯(lián)關(guān)系,根據(jù)復雜對象中關(guān)聯(lián)關(guān)系的描述,可以構(gòu)建出多個查詢預取隊列。因為用戶根據(jù)實際數(shù)據(jù)需求參與關(guān)聯(lián)關(guān)系的確定,所以查詢預取隊列中的對象被訪問的機率是很大的甚至是100%。當用戶查詢某個對象A時,后臺會繼續(xù)查詢隊列中的下一個對象B,當操作到對象B的數(shù)據(jù)時,后臺會繼續(xù)查詢B的下一個對象C的數(shù)據(jù),以提高查詢的速度。當用戶獲取到一個對象查詢數(shù)據(jù)后,可以在內(nèi)存中獲取隊列中下一個對象的數(shù)據(jù),減少了再去查詢數(shù)據(jù)庫的時間。
在實際應用中,頻繁地訪問數(shù)據(jù)庫,會對應用的性能造成很大影響。為了降低訪問數(shù)據(jù)庫的頻率,可以把需要經(jīng)常被訪問的業(yè)務數(shù)據(jù)存放在緩存中,并且通過特定的機制來保證緩存中的數(shù)據(jù)與數(shù)據(jù)庫數(shù)據(jù)同步[10]。本方案的緩存思想是抽取所有對象中的關(guān)鍵對象形成緩存對象鏈表,對鏈表中的對象數(shù)據(jù)進行本地緩存和實時更新。在用戶的第一次查詢中,如果發(fā)現(xiàn)查詢對象是鏈表中的關(guān)鍵對象,則將查詢結(jié)果對象駐留在內(nèi)存中,供其它應用再次查詢時直接使用,減少訪問數(shù)據(jù)庫的時間。當用戶通過關(guān)鍵對象的修改接口更新關(guān)鍵對象的數(shù)據(jù)到數(shù)據(jù)庫后,數(shù)據(jù)訪問也同步更新緩存中的關(guān)鍵對象數(shù)據(jù),保證內(nèi)存塊中關(guān)鍵對象的數(shù)據(jù)最新。
復雜對象的數(shù)據(jù)訪問在某項目中的使用示例步驟如下:
1)用戶抽取業(yè)務數(shù)據(jù)庫模型到元數(shù)據(jù)庫中,形成數(shù)據(jù)庫邏輯視圖。
2)基于元數(shù)據(jù)模型,生成交通設施對象,選擇關(guān)心的一張主表交通設施及其關(guān)聯(lián)表,選擇主表中所有字段和關(guān)聯(lián)表中名稱字段,自動生成關(guān)聯(lián)的查詢SQL,主子表級聯(lián)操作的增刪改SQL。
生成橋梁對象,選擇表中的字段交通設施內(nèi)碼、橋長、橋?qū)?、水深、歸屬地區(qū)、可停靠船的最大噸位等,再在提示的關(guān)聯(lián)表中選擇交通設施表,選擇關(guān)聯(lián)屬性交通設施名稱,自動生成關(guān)聯(lián)的查詢SQL,主子表級聯(lián)操作的增刪改SQL。類似地生成機場對象。
生成人防設施對象,用戶通過業(yè)務對象生成工具瀏覽專業(yè)庫中的數(shù)據(jù)表,選擇關(guān)心的一張主表人防設施表,選擇表中的字段人防設施內(nèi)碼、防護等級ID(關(guān)聯(lián)防護等級表)、建筑面積、管理單位、可儲藏人數(shù)、其它描述,質(zhì)量現(xiàn)狀I(lǐng)D(關(guān)聯(lián)質(zhì)量現(xiàn)狀表)等,再在提示的關(guān)聯(lián)表中選擇防護等級表、質(zhì)量現(xiàn)狀表,選擇關(guān)聯(lián)屬性防護等級名稱字段和質(zhì)量現(xiàn)狀描述字段,自動生成關(guān)聯(lián)的查詢SQL,主子表級聯(lián)操作的增刪改SQL。
3)由2)生成的4個對象構(gòu)建的樹形成復雜對象公共設施,構(gòu)建兩個查詢預取隊列:查詢11、查詢12、查詢13和查詢21、查詢22,如圖3所示。針對制作好的一系列對象生成對象接口動態(tài)庫文件,用戶調(diào)用對象的增刪改查接口用于數(shù)據(jù)訪問。
圖3 對象間的關(guān)聯(lián)關(guān)系
4)數(shù)據(jù)訪問根據(jù)復雜業(yè)務對象公共設施描述中對象操作的執(zhí)行順序,按照查詢11至查詢13或查詢21至查詢22的順序查詢和預取對象數(shù)據(jù),形成查詢預取隊列;設置交通設施對象為關(guān)鍵對象,常駐內(nèi)存中,以提高這個對象的數(shù)據(jù)訪問速度。
5)按照圖3所示的流程,按查詢11至查詢13的查詢操作序列查詢交通設施對象,查詢數(shù)據(jù)庫返回結(jié)果,反射成交通設施對象集,根據(jù)預取隊列的描述,利用空閑時間提前執(zhí)行下一個對象橋梁對象的查詢操作,然后用戶可以操作交通設施對象及其關(guān)聯(lián)子對象橋梁,當操作橋梁數(shù)據(jù)時,再提前執(zhí)行下一個對象機場對象的查詢。因為交通設施為關(guān)鍵對象,因此該對象數(shù)據(jù)駐留在內(nèi)存中。如果用戶更新了交通設施這個對象中的數(shù)據(jù),數(shù)據(jù)訪問同時也要刷新駐留在內(nèi)存的交通設施對象數(shù)據(jù)。
通過復雜對象化數(shù)據(jù)訪問,使專業(yè)人員將精力集中在業(yè)務邏輯處理上,不必關(guān)心數(shù)據(jù)庫底層操作的細節(jié)。由于數(shù)據(jù)訪問中的對象尤其是帶有業(yè)務流程的復雜對象是綜合了軍事指揮控制領(lǐng)域應用的數(shù)據(jù)訪問需求提煉出來的,所以具有一定的通用性,該系統(tǒng)可以應用到指控領(lǐng)域的各個項目中去,大大提高項目的開發(fā)效率和可擴展性。
[1]吳姍姍,彭向陽.基于XML的通用數(shù)據(jù)庫訪問引擎的設計與實現(xiàn)[J].指揮信息系統(tǒng)與技術(shù),2010(1):55-59.
[2]Christian Bauer,Gavin King.Hibernate in Action[M].USA:Manning Publication,2004:15-26.
[3]Pierre Henri Kuaté,Christian Bauer,Gavin King.NHibernate In Action[M].Manning Publications,2007:36-40.
[4]高昂,衛(wèi)文學.基于Hibernate與Struts框架的數(shù)據(jù)持久化應用研究[J].計算機應用,2005,25(12):2818-2819.
[5]李斌勇,李慶.基于NHibernate的ORM映射機制研究[J].計算機技術(shù)與發(fā)展,2009(7):32-34.
[6]萬長鵬,唐慧佳.基于ASP.NET+Castle框架的旅游管理系統(tǒng)的設計[J].成都信息工程學院學報,2007(4):458-461.
[7]周浩,張祖平.面向?qū)ο蟮某志没夹g(shù)的研究與實現(xiàn)[J].企業(yè)技術(shù)開發(fā),2010(9):4-5.
[8]武亞青.數(shù)據(jù)共享環(huán)境研究[J].指揮信息系統(tǒng)與技術(shù),2011(2):35-40.
[9]Ben Wiedermann,William R C.Extracting queries by static analysis of t ransparent persiste nce[J].ACM SIGPLAN Notices,2007,42(1):199-210.
[10]孫衛(wèi)琴.精通Hibernate:java對象持久化技術(shù)詳解[M].北京:電子工業(yè)出版社,2005:173-176.