雷明濤,李 瓊,施榮榮,周 剛,王 磊
(1.中國電子科技集團(tuán)公司第二十八研究所,江蘇 南京 210007;2.武警江蘇省總隊(duì),江蘇 南京 210019)
面向?qū)ο笞鳛橐环N軟件開發(fā)方法,其概念和應(yīng)用已經(jīng)遠(yuǎn)遠(yuǎn)超越了軟件設(shè)計(jì)和軟件開發(fā)的范疇,擴(kuò)展到如數(shù)據(jù)庫系統(tǒng)、交互式解碼、應(yīng)用平臺(tái)和分布式系統(tǒng)等領(lǐng)域[1]。面向?qū)ο髷?shù)據(jù)庫訪問技術(shù)是支持將數(shù)據(jù)庫的數(shù)據(jù)當(dāng)做對(duì)象來模擬和創(chuàng)造的一種數(shù)據(jù)庫訪問技術(shù),而面向?qū)ο髷?shù)據(jù)模型是構(gòu)成面向?qū)ο髷?shù)據(jù)庫訪問技術(shù)的基礎(chǔ)[2],面向?qū)ο蟮臄?shù)據(jù)庫訪問接口設(shè)計(jì)的關(guān)鍵是其新型的數(shù)據(jù)模型對(duì)象設(shè)計(jì),以及數(shù)據(jù)模型與數(shù)據(jù)庫結(jié)構(gòu)之間的對(duì)象匹配。
目前,常用的數(shù)據(jù)模型與數(shù)據(jù)庫結(jié)構(gòu)之間的對(duì)象匹配方法主要有基于OMG的CORBA、Sun的J2EE 和Microsoft DNA的對(duì)象關(guān)系映射(Object Relational Mapping,ORM)、基于數(shù)據(jù)字典的對(duì)象化匹配和模糊對(duì)象匹配。模糊對(duì)象匹配方法基于可能性理論和模糊數(shù)據(jù)的語義測(cè)度,通過計(jì)算兩個(gè)模糊對(duì)象等價(jià)度和必要度實(shí)現(xiàn)模糊對(duì)象匹配[3],這種方法一般應(yīng)用于異構(gòu)數(shù)據(jù)的集成和清洗,不適用于通用數(shù)據(jù)庫訪問;基于CORBA/J2EE/DNA的ORM技術(shù)通過使用描述對(duì)象和數(shù)據(jù)庫之間映射的元數(shù)據(jù),將面向?qū)ο笳Z言程序中的對(duì)象自動(dòng)持久化到關(guān)系數(shù)據(jù)庫中,從而實(shí)現(xiàn)了數(shù)據(jù)模型與數(shù)據(jù)庫結(jié)構(gòu)的自動(dòng)匹配[4-8],但當(dāng)數(shù)據(jù)庫結(jié)構(gòu)發(fā)生變化時(shí)需要重新構(gòu)建描述對(duì)象,可擴(kuò)展性較差;而基于數(shù)據(jù)字典的對(duì)象化匹配方法根據(jù)數(shù)據(jù)庫元數(shù)據(jù)生成數(shù)據(jù)字典[9-12],由數(shù)據(jù)字典自動(dòng)構(gòu)建數(shù)據(jù)模型,特別是通過自適應(yīng)數(shù)據(jù)字典技術(shù)在數(shù)據(jù)庫結(jié)構(gòu)和數(shù)據(jù)模型之間建立“動(dòng)態(tài)耦合”的方法,實(shí)現(xiàn)了數(shù)據(jù)模型隨數(shù)據(jù)庫結(jié)構(gòu)的變化而變化的自適應(yīng)對(duì)象匹配[11]。
本文正是基于數(shù)據(jù)字典的自動(dòng)對(duì)象匹配方法提出了一種面向?qū)ο蟮耐ㄓ脭?shù)據(jù)庫訪問接口泛化方法,通過基于數(shù)據(jù)字典的編解碼技術(shù)實(shí)現(xiàn)數(shù)據(jù)庫訪問請(qǐng)求泛化、數(shù)據(jù)庫訪問處理泛化和數(shù)據(jù)庫訪問結(jié)果泛化。
本文提出的這種通用數(shù)據(jù)庫訪問接口泛化方法基于自建的數(shù)據(jù)字典技術(shù),數(shù)據(jù)字典可以從數(shù)據(jù)庫系統(tǒng)的數(shù)據(jù)目錄中自動(dòng)化提取,數(shù)據(jù)字典分為用戶數(shù)據(jù)字典、表/視圖數(shù)據(jù)字典和字段數(shù)據(jù)字典三類[11],三類數(shù)據(jù)字典生成后以文件的形式存儲(chǔ),并在數(shù)據(jù)庫訪問接口初始化時(shí)加載到內(nèi)存中。數(shù)據(jù)字典結(jié)構(gòu)及其關(guān)聯(lián)關(guān)系示意圖如圖1所示。
圖1 數(shù)據(jù)字典結(jié)構(gòu)及其關(guān)聯(lián)關(guān)系
數(shù)據(jù)字典文件分為文件頭和數(shù)據(jù)字典內(nèi)容兩部分,文件頭的格式相同,文件頭和數(shù)據(jù)字典內(nèi)容如下:
(1)數(shù)據(jù)字典文件頭:包括文件名、文件長度、記錄個(gè)數(shù)、單個(gè)記錄的長度,校驗(yàn)碼和記錄起始位置的偏移量;
(2)用戶數(shù)據(jù)字典:包括用戶名、用戶ID和用戶下的表/視圖數(shù)目;
(3)表數(shù)據(jù)字典:包括表名、用戶的ID、表ID、表的字段數(shù)目、表的主鍵字段數(shù)目和表的主鍵字段ID;
(4)字段數(shù)據(jù)字典:包括字段名、用戶ID、表ID、字段ID、字段類型和字段長度。
數(shù)據(jù)字典中的字段類型是與數(shù)據(jù)庫字段類型對(duì)應(yīng)的編程語言中的類型,比如:數(shù)據(jù)庫的整數(shù)對(duì)應(yīng)編程語言的整數(shù)類型,浮點(diǎn)數(shù)對(duì)應(yīng)浮點(diǎn)數(shù),字符串對(duì)應(yīng)字符數(shù)組,時(shí)間對(duì)應(yīng)時(shí)間結(jié)構(gòu)體,字段長度為編程語言中的類型長度。這樣根據(jù)數(shù)據(jù)字典就可以自動(dòng)生成編程語言的數(shù)據(jù)結(jié)構(gòu)。
假設(shè)用戶U有一張數(shù)據(jù)庫表T,表T有m個(gè)字段,分別為(T1,T2,…,Tm),根據(jù)數(shù)據(jù)字典生成的編程語言數(shù)據(jù)結(jié)構(gòu)為S,S的m個(gè)數(shù)據(jù)成員分別為(S1,S2,…,Sm)。表T和數(shù)據(jù)結(jié)構(gòu)S的對(duì)象關(guān)系映射示意圖如圖2所示。
圖2 表T和數(shù)據(jù)結(jié)構(gòu)S的對(duì)象關(guān)系映射
用戶U的數(shù)據(jù)字典為Du,表T的表數(shù)據(jù)字典為DT,則字段(T1,T2,…,Tm)的字段數(shù)據(jù)字典分別為,字段數(shù)據(jù)字典中字段(T1,T2,…,Tm)的字段長度為(L1,L2,…,Lm),數(shù)據(jù)結(jié)構(gòu)S的長度為L。
數(shù)據(jù)結(jié)構(gòu)S的內(nèi)存存儲(chǔ)示意圖如圖3所示。
圖3 數(shù)據(jù)結(jié)構(gòu)S的內(nèi)存存儲(chǔ)示意
由圖3可知:
數(shù)據(jù)庫訪問請(qǐng)求的入?yún)⒅泻瑪?shù)據(jù)訪問的用戶U、表T和泛化后的S的對(duì)象指針PS,將數(shù)據(jù)庫訪問請(qǐng)求自適應(yīng)對(duì)象的方法為:先通過用戶名U找到該用戶的數(shù)據(jù)字典Du,然后根據(jù)用戶名查到用戶U的數(shù)據(jù)字典Du,再根據(jù)表名在Du中找到表T的數(shù)據(jù)字典DT,進(jìn)而可以獲取表T的字段(T1,T2,…,Tm)的字段字典(DT1,DT2,…,DTm),從字段數(shù)據(jù)字典中即可獲?。⊿1,S2,…,Sm)在數(shù)據(jù)結(jié)構(gòu)S中的存儲(chǔ)長度(L1,L2,…,Lm)。由公式(1)可知數(shù)據(jù)結(jié)構(gòu)S的長度L,從指針PS起始的L個(gè)字節(jié)存儲(chǔ)的即為數(shù)據(jù)結(jié)構(gòu)S的對(duì)象。
設(shè)(B1,B2,…,Bm)為(S1,S2,…,Sm)在PS中存儲(chǔ)的起始字節(jié),則:
則從PS的起始地址,根據(jù)數(shù)據(jù)結(jié)構(gòu)S的成員(S1,S2,…,Sm)的長度(L1,L2,…,Lm)按位讀取,即可獲取PS指向的類型為S的對(duì)象的成員(S1,S2,…,Sm)的值。
設(shè)f(x,y)(x<y)表示起始地址為x、結(jié)束地址為y的一段內(nèi)存的存儲(chǔ)值,當(dāng)1≤i≤m時(shí)有:
將根據(jù)公式(3)獲取的數(shù)據(jù)結(jié)構(gòu)S的成員(S1,S2,…,Sm)與數(shù)據(jù)庫用戶U的表T的字段(T1,T2,…,Tm)一一對(duì)應(yīng)匹配,即可實(shí)現(xiàn)數(shù)據(jù)庫訪問請(qǐng)求中編程語言數(shù)據(jù)結(jié)構(gòu)與數(shù)據(jù)庫表結(jié)構(gòu)自動(dòng)適配。
當(dāng)數(shù)據(jù)庫請(qǐng)求為查詢請(qǐng)求時(shí),需要將從數(shù)據(jù)庫中查詢到的每條記錄轉(zhuǎn)換成編程語言的數(shù)據(jù)結(jié)構(gòu)的格式。假設(shè):查詢所有字段的內(nèi)容,泛化的指針Po為查詢結(jié)果起始地址,將查詢結(jié)果轉(zhuǎn)化為編程語言的數(shù)據(jù)對(duì)象的過程即為將查詢到的字段(T1,T2,…,Tm)的值轉(zhuǎn)換成指針Po指向的數(shù)據(jù)對(duì)象S的數(shù)據(jù)成員(S1,S2,…,Sm)的過程。
使用同2.1中方法同樣獲取到表T的字段(T1,T2,…,Tm)的字段字典(DT1,DT2,…,DTm)和輸出結(jié)果的數(shù)據(jù)類型S,以及其對(duì)應(yīng)的編程語言數(shù)據(jù)結(jié)構(gòu)S的成員(S1,S2,…,Sm)及其數(shù)據(jù)長度(L1,L2,…,Lm),依次提取數(shù)據(jù)庫中字段(T1,T2,…,Tm)的值,并將其賦給(S1,S2,…,Sm),然后將Si(1≤i≤m)按位賦給起始地址為Po的地址,即:
根據(jù)公式(4)將Po起始的內(nèi)存地址分為了m份,每份的長度依次為(L1,L2,…,Lm),將Si(1≤i≤m)的值存在第i個(gè)單元即可實(shí)現(xiàn)數(shù)據(jù)庫查詢結(jié)果自動(dòng)適配編程語言數(shù)據(jù)結(jié)構(gòu)對(duì)象。
當(dāng)查詢數(shù)據(jù)表T的部分字段時(shí),將查詢結(jié)果自動(dòng)適配對(duì)象的方法與查詢?nèi)繒r(shí)類似,假設(shè)表T的某個(gè)成員Tn(1≤n≤m)沒有被查詢,則只需要進(jìn)行查詢結(jié)果對(duì)象化時(shí)跳過Sn字段長度為Ln的內(nèi)存地址,即在1≤i≤n和n<i≤m兩個(gè)區(qū)間分別按照公式(4)為指針Po指向的內(nèi)存地址賦值,即可實(shí)現(xiàn)將查詢數(shù)據(jù)庫表部分字段的結(jié)果進(jìn)行自動(dòng)適配對(duì)象。
為實(shí)現(xiàn)數(shù)據(jù)庫訪問請(qǐng)求的統(tǒng)一,采用數(shù)據(jù)字典技術(shù)對(duì)數(shù)據(jù)庫訪問請(qǐng)求進(jìn)行重新編碼的方法進(jìn)行泛化,這種方法將數(shù)據(jù)庫訪問請(qǐng)求泛化為根據(jù)數(shù)據(jù)字典打包后的一段內(nèi)存指針。數(shù)據(jù)訪問請(qǐng)求要素主要有數(shù)據(jù)庫名稱、數(shù)據(jù)庫表/視圖名稱,數(shù)據(jù)庫操作類型(插入、刪除、修改和查詢)、表記錄數(shù)據(jù)和查詢條件(刪除、修改和查詢)。數(shù)據(jù)庫請(qǐng)求泛化后的數(shù)據(jù)請(qǐng)求由數(shù)據(jù)庫請(qǐng)求數(shù)據(jù)頭、數(shù)據(jù)庫表記錄數(shù)據(jù)頭、數(shù)據(jù)庫表字段數(shù)據(jù)頭和字段數(shù)據(jù)值組成。
數(shù)據(jù)庫請(qǐng)求數(shù)據(jù)頭如表1所示。
表1 數(shù)據(jù)庫請(qǐng)求數(shù)據(jù)頭
數(shù)據(jù)庫表記錄數(shù)據(jù)頭如表2所示。
表2 數(shù)據(jù)庫表記錄數(shù)據(jù)頭
數(shù)據(jù)庫表字段數(shù)據(jù)頭如表3所示。
表3 數(shù)據(jù)庫表字段數(shù)據(jù)頭
數(shù)據(jù)庫請(qǐng)求泛化首先根據(jù)數(shù)據(jù)庫名稱和表/視圖名稱獲取數(shù)據(jù)字典中的數(shù)據(jù)庫數(shù)據(jù)字典、表/視圖數(shù)據(jù)字典和字段數(shù)據(jù)字典,根據(jù)這些數(shù)據(jù)字典打包請(qǐng)求數(shù)據(jù)包頭和表記錄數(shù)據(jù)包頭,然后根據(jù)字段數(shù)據(jù)字典的順序依次打包字段數(shù)據(jù)包頭和字段值,字段值為按照字段數(shù)據(jù)字典和圖2描述的數(shù)據(jù)結(jié)構(gòu)S讀取的S的成員值,泛化后的數(shù)據(jù)庫請(qǐng)求內(nèi)存存儲(chǔ)示意圖如圖4所示。
圖4 泛化后的數(shù)據(jù)庫請(qǐng)求內(nèi)存存儲(chǔ)示意
數(shù)據(jù)庫訪問處理泛化是數(shù)據(jù)庫訪問請(qǐng)求泛化的反過程,首先解析數(shù)據(jù)庫請(qǐng)求包頭,獲取請(qǐng)求中攜帶的數(shù)據(jù)請(qǐng)求數(shù)目,然后根據(jù)數(shù)據(jù)字典獲取數(shù)據(jù)請(qǐng)求記錄操作的數(shù)據(jù)庫、數(shù)據(jù)表/視圖、操作類型、字段名、字段值,然后根據(jù)這些要素構(gòu)建數(shù)據(jù)庫方法訪問數(shù)據(jù)庫。數(shù)據(jù)庫訪問處理泛化的流程圖如圖5所示。
圖5 數(shù)據(jù)庫訪問處理泛化的流程
由于采用了基于數(shù)據(jù)字典的訪問處理機(jī)制,對(duì)數(shù)據(jù)訪問的處理流程不依賴于數(shù)據(jù)庫和數(shù)據(jù)庫表,可以實(shí)現(xiàn)一個(gè)數(shù)據(jù)庫訪問接口、一個(gè)處理流程處理所有數(shù)據(jù)庫表的訪問,真正實(shí)現(xiàn)了數(shù)據(jù)庫訪問處理的泛化。數(shù)據(jù)庫訪問處理泛化的具體流程如下:
(1)數(shù)據(jù)庫訪問接口收到泛化后的數(shù)據(jù)庫訪問請(qǐng)求;
(2)根據(jù)請(qǐng)求中攜帶的數(shù)據(jù)庫ID和表/視圖ID查詢數(shù)據(jù)字典;
(3)獲取到指定數(shù)據(jù)庫的數(shù)據(jù)字典、指定表/視圖的數(shù)據(jù)字典以及表/視圖下的所有字段的數(shù)據(jù)字典;
(4)基于數(shù)據(jù)字典根據(jù)圖2和圖3構(gòu)造請(qǐng)求對(duì)象的數(shù)據(jù)結(jié)構(gòu);
(5)根據(jù)圖3將泛化后的數(shù)據(jù)訪問請(qǐng)求中的數(shù)據(jù)結(jié)構(gòu)S還原,獲取到每個(gè)成員的值;
(6)根據(jù)圖2將還原后的數(shù)據(jù)結(jié)構(gòu)S的數(shù)據(jù)成員與數(shù)據(jù)庫表的字段自動(dòng)適配;
(7)根據(jù)請(qǐng)求中的數(shù)據(jù)庫操作類型構(gòu)造數(shù)據(jù)庫方法并訪問數(shù)據(jù)庫。
當(dāng)數(shù)據(jù)庫訪問請(qǐng)求為插入、更新和刪除等數(shù)據(jù)操縱語言(Data Manipulation Language,DML)操作時(shí),直接返回?cái)?shù)據(jù)庫訪問成功與否即可,此處不再贅述;當(dāng)為數(shù)據(jù)查詢語言(Data Query Language,DQL)查詢操作時(shí),數(shù)據(jù)庫訪問接口除返回成功與否外,還需要提供查詢結(jié)果的提取功能,基于數(shù)據(jù)字典的數(shù)據(jù)庫訪問處理機(jī)制,同樣可以實(shí)現(xiàn)一個(gè)數(shù)據(jù)庫查詢結(jié)果提取接口、一個(gè)查詢結(jié)果提取流程適用于所有數(shù)據(jù)庫表的查詢結(jié)果提取,將查詢結(jié)果轉(zhuǎn)化為編程語言數(shù)據(jù)對(duì)象的格式,可以供編程語言以該數(shù)據(jù)對(duì)象的形式直接訪問,從而實(shí)現(xiàn)了數(shù)據(jù)庫查詢結(jié)果的泛化。數(shù)據(jù)庫查詢結(jié)果泛化的處理流程圖如圖6所示。
圖6 數(shù)據(jù)庫查詢結(jié)果泛化處理流程
數(shù)據(jù)庫查詢結(jié)果泛化的具體流程如下:
(1)根據(jù)數(shù)據(jù)庫用戶名和表/視圖名查詢數(shù)據(jù)字典;
(2)獲取到指定數(shù)據(jù)庫的數(shù)據(jù)字典、指定表/視圖的數(shù)據(jù)字典以及表/視圖下的所有字段的數(shù)據(jù)字典;
(3)基于數(shù)據(jù)字典根據(jù)圖2和圖3構(gòu)造查詢結(jié)果在編程語言中對(duì)象的數(shù)據(jù)結(jié)構(gòu);
(4)逐個(gè)提取查詢結(jié)果的字段值;
(5)根據(jù)圖2和圖3中所建立的數(shù)據(jù)庫表字段與編程語言數(shù)據(jù)結(jié)構(gòu)成員的對(duì)象化關(guān)系,實(shí)現(xiàn)數(shù)據(jù)庫查詢結(jié)果與編程語言數(shù)據(jù)結(jié)構(gòu)的自動(dòng)適配,將查詢結(jié)果轉(zhuǎn)化為編程語言數(shù)據(jù)對(duì)象的格式;
(6)將所有字段提取完畢后,數(shù)據(jù)訪問接口以編程語言對(duì)象的形式向應(yīng)用返回查詢結(jié)果。
本文基于數(shù)據(jù)字典技術(shù),提出了一種通用數(shù)據(jù)庫訪問接口的泛化方法,通過數(shù)據(jù)庫請(qǐng)求的泛化實(shí)現(xiàn)對(duì)數(shù)據(jù)庫訪問接口的標(biāo)準(zhǔn)化,通過對(duì)數(shù)據(jù)庫訪問處理的泛化實(shí)現(xiàn)了數(shù)據(jù)庫訪問處理流程的標(biāo)準(zhǔn)化,通過數(shù)據(jù)庫查詢結(jié)果的泛化實(shí)現(xiàn)了查詢結(jié)果提取接口的標(biāo)準(zhǔn)化,通過對(duì)數(shù)據(jù)庫訪問處理的泛化和數(shù)據(jù)庫查詢結(jié)果的泛化實(shí)現(xiàn)了對(duì)所有數(shù)據(jù)庫表處理的標(biāo)準(zhǔn)化,從而實(shí)現(xiàn)了同一套數(shù)據(jù)庫接口對(duì)數(shù)據(jù)庫所有表的DML和DQL操作。經(jīng)實(shí)踐驗(yàn)證,基于數(shù)據(jù)字典的通用數(shù)據(jù)庫訪問接口泛化方法能夠?qū)崿F(xiàn)面向?qū)ο蟮臄?shù)據(jù)庫訪問中間件與數(shù)據(jù)庫結(jié)構(gòu)的“解耦和”,具有良好的通用性。