《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 其他 > 业界动态 > Java类封装关系数据库中数据访问的通用方案

Java类封装关系数据库中数据访问的通用方案

2008-12-19
作者:彭德云* 王嘉祯* 陈卫**

1?引言?

??? 目前的數(shù)據(jù)庫(kù)管理系統(tǒng)" title="管理系統(tǒng)">管理系統(tǒng)(DBMS)中基本上是關(guān)系型數(shù)據(jù)庫(kù)(RDBMS)占據(jù)著主導(dǎo)地位。從形式上來(lái)說(shuō),關(guān)系數(shù)據(jù)庫(kù)" title="關(guān)系數(shù)據(jù)庫(kù)">關(guān)系數(shù)據(jù)庫(kù)是一系列行列規(guī)整的表的集合,但邏輯上數(shù)據(jù)庫(kù)中數(shù)據(jù)是對(duì)現(xiàn)實(shí)世界中事物的抽象描述。而面向?qū)ο?/a>" title="面向?qū)ο?>面向?qū)ο?/a>建模的過(guò)程也是對(duì)事物的抽象過(guò)程。所以關(guān)系數(shù)據(jù)庫(kù)中的數(shù)據(jù)和對(duì)象二者間存在一種以其共同描述的現(xiàn)實(shí)世界中的事物為紐帶的聯(lián)系。利用面向?qū)ο笏枷雽?duì)關(guān)系數(shù)據(jù)庫(kù)中的數(shù)據(jù)訪問(wèn)" title="數(shù)據(jù)訪問(wèn)">數(shù)據(jù)訪問(wèn)進(jìn)行抽象和封裝,可以有效地提高系統(tǒng)性能、降低開發(fā)成本。本文對(duì)傳統(tǒng)的數(shù)據(jù)庫(kù)訪問(wèn)技術(shù)的用Java類進(jìn)行了面向?qū)ο蟮某橄蠛头庋b,并就其中目前廣泛存在的問(wèn)題" title="存在的問(wèn)題">存在的問(wèn)題提出了一種通用的解決方案,極大地提高了開發(fā)效率。

2?基本的面向?qū)ο蟮姆庋b方法?

??? 面向?qū)ο笏枷胧悄壳白顬榱餍械脑O(shè)計(jì)思想。充分利用面向?qū)ο蟮乃枷?,?duì)數(shù)據(jù)庫(kù)數(shù)據(jù)訪問(wèn)進(jìn)行抽象和封裝,將帶來(lái)以下幾個(gè)好處:①對(duì)數(shù)據(jù)和過(guò)程進(jìn)行抽象封裝,提高了系統(tǒng)的模塊獨(dú)立性,降低了系統(tǒng)的耦合度;②對(duì)相關(guān)實(shí)體的封裝,有利于構(gòu)件復(fù)用;③信息隱蔽,減少發(fā)生錯(cuò)誤時(shí)副作用的傳播;④繼承性使得對(duì)超類的修改可以立即作用到所有子類。?

2.1 實(shí)體類?

??? 關(guān)系數(shù)據(jù)庫(kù)數(shù)據(jù)訪問(wèn)操作,可以利用面向?qū)ο蟮乃枷脒M(jìn)行封裝,可以建立“表(或視圖等)—對(duì)象”的對(duì)應(yīng)關(guān)系,把數(shù)據(jù)的取、增、刪、改操作封裝成類方法。

??? 在數(shù)據(jù)庫(kù)中,大量的數(shù)據(jù)訪問(wèn)許多是對(duì)表最基本的數(shù)據(jù)庫(kù)操作(對(duì)記錄的取、增、刪、改操作)或這些操作的組合。關(guān)系數(shù)據(jù)庫(kù)中的表可以映射為類,表的字段可以映射成類的屬性,對(duì)表的操作可以映射成類的方法,表的記錄(行)可以映射成類的對(duì)象。現(xiàn)在以一個(gè)簡(jiǎn)化的學(xué)校信息管理系統(tǒng)為例說(shuō)明數(shù)據(jù)的訪問(wèn)過(guò)程。圖1中每個(gè)方框表示一個(gè)實(shí)體,在數(shù)據(jù)庫(kù)中每個(gè)實(shí)體用一個(gè)表表示(見圖2)。

??? 如上述的學(xué)校管理系統(tǒng)中就可以建立學(xué)校類、學(xué)生類、教師類、課程類等。一個(gè)實(shí)體類的屬性通常以對(duì)應(yīng)的表的字段命名;其方法通常是以對(duì)某個(gè)字段信息的操作命名。比如學(xué)生類有學(xué)生編號(hào)、姓名、性別等屬性,有取編號(hào)、設(shè)置編號(hào)等以getXX和setXX的方法(XX對(duì)應(yīng)于某一屬性)。

2.2實(shí)體管理類?

??? 在對(duì)“實(shí)體”(比如學(xué)生Student)抽象和包裝的過(guò)程中,往往需要一個(gè)對(duì)應(yīng)的“實(shí)體管理類”負(fù)責(zé)對(duì)實(shí)體的管理工作。因?yàn)椤皩?shí)體對(duì)象”本身側(cè)重于對(duì)單個(gè)實(shí)體的描述,而數(shù)據(jù)庫(kù)訪問(wèn)通常是對(duì)一組滿足特定條件的記錄(對(duì)應(yīng)于一組實(shí)體對(duì)象)進(jìn)行操作,所以需要在“YY實(shí)體” 層(YY表示某類實(shí)體名)之上有一具有對(duì)應(yīng)管理功能的類層次,稱之為“YY實(shí)體管理類”。比如“學(xué)生類”(Student)的管理類為“學(xué)生管理類”(StudentManage)。實(shí)體管理類主要的方法對(duì)應(yīng)于相應(yīng)實(shí)體的查找、增加、刪除、修改、列表等操作。一個(gè)實(shí)體管理類的方法通常是一組有g(shù)etYY、addYY、deleteYY、editYY、listYY特征的成員函數(shù)。

??? 假設(shè)現(xiàn)需查詢?cè)谔囟ǔ煽?jī)段的學(xué)生,就可以調(diào)用學(xué)生管理類的以成績(jī)段為參數(shù)的類方法得到所有滿足查詢條件的學(xué)生,如果想得到這些學(xué)生的信息,則可以調(diào)用學(xué)生對(duì)象的“getXX”方法實(shí)現(xiàn)。下面以學(xué)校管理系統(tǒng)的學(xué)生實(shí)體為例進(jìn)行抽象和封裝。

public abstract class Student{//學(xué)生類?

? String id = null;//學(xué)生編號(hào)?

? String name = null;//學(xué)生姓名?

? …?

? public abstract void setId(String _id);//設(shè)置學(xué)生實(shí)體編號(hào)?

? public abstract String getId();//取學(xué)生實(shí)體編號(hào)?

? ...?

}?

下面這個(gè)類是相應(yīng)的一個(gè)學(xué)生管理類的代碼: ?

public class StudentManage{//學(xué)生管理類?

? public Student findStudentById(String _id) {…}//查找某一編號(hào)的學(xué)生?

public boolean deleteStudentById(String _id) {…}//刪除某一編號(hào)的學(xué)生?

? ...?

}?

2.3 存在問(wèn)題?

??? 可以看出,通過(guò)以上的對(duì)學(xué)生信息相關(guān)操作的封裝,對(duì)學(xué)生信息的程序處理邏輯上更加清晰,同時(shí)也提高了軟件的復(fù)用程度,降低了系統(tǒng)的偶合度。但是該模式也有明顯的弊端:①由于實(shí)際系統(tǒng)中大量表的存在,要編寫大量相應(yīng)的封裝類(實(shí)體類和相應(yīng)實(shí)體的管理類),封裝類的個(gè)數(shù)隨著表的數(shù)量(N)成約為N*2的比率增長(zhǎng); ②封裝類的大小(主要是成員變量和成員函數(shù)的個(gè)數(shù))隨著表的字段個(gè)數(shù)(M)的增加成約為M*λ(λ為封裝類的平均成員函數(shù)個(gè)數(shù))的比率增長(zhǎng);③對(duì)數(shù)據(jù)庫(kù)中表結(jié)構(gòu)的變動(dòng)會(huì)傳播到類的定義上來(lái)。?

3?通用解決方案?

3.1解決思路?

??? 上面所提出的抽象和封裝方案問(wèn)題在于實(shí)體的特征和功能(對(duì)應(yīng)于類的屬性和方法)是靜態(tài)的:實(shí)體的特征和功能在類的定義時(shí)就確定下來(lái)了(以字段命名),在程序的運(yùn)行過(guò)程中也無(wú)法動(dòng)態(tài)改變或更新。這樣就必須把幾乎所有的字段及其操作都對(duì)應(yīng)成類的屬性和方法。通用解決方案就是試圖找到一條能夠克服以上弊端的途徑。其核心思想是將數(shù)據(jù)庫(kù)表及其字段信息存儲(chǔ)在數(shù)據(jù)庫(kù)中,動(dòng)態(tài)地創(chuàng)建實(shí)體。該實(shí)體類的定義不與特定的表關(guān)聯(lián),但能與某個(gè)表動(dòng)態(tài)關(guān)聯(lián)并執(zhí)行特定的功能。

??? 該方案的實(shí)現(xiàn)有兩個(gè)問(wèn)題必須解決:

①動(dòng)態(tài)創(chuàng)建邏輯實(shí)體。動(dòng)態(tài)創(chuàng)建邏輯實(shí)體需要在給定實(shí)體名的條件下能獲得該實(shí)體在特定條件下所擁有的特征。實(shí)體特征實(shí)際上是一個(gè)<表名,字段名>的二元組。目前的解決方法是在庫(kù)中預(yù)先創(chuàng)建一個(gè)實(shí)體特征表,有三個(gè)基本字段:表名、字段名、字段類型。

②動(dòng)態(tài)賦予邏輯實(shí)體的特征和功能。目前的解決方法是把實(shí)體的特征和特征類型用哈希表(Hashtable)的形式存儲(chǔ)在類中。實(shí)體特征的增、刪可以通過(guò)對(duì)哈希表的操作(put和remove)實(shí)現(xiàn)。一個(gè)實(shí)體屬性一般有兩個(gè)實(shí)體方法與之對(duì)應(yīng),即取、設(shè)置該屬性值的操作。如果把屬性名稱作為實(shí)體方法的參數(shù)以標(biāo)識(shí)對(duì)某個(gè)屬性值的操作,這樣就可以避免為每個(gè)屬性值都要編寫對(duì)應(yīng)的方法(getXX和setXX)。

??? 下面就以在學(xué)校信息系統(tǒng)中的應(yīng)用進(jìn)行說(shuō)明。在庫(kù)中建立一實(shí)體特征表UNIT_ATTR,有三個(gè)字段:實(shí)體名(TABLE_NAME),實(shí)體屬性(ATTRIBUTE_NAME),屬性類型(ATTRIBUTE_TYPE)。定義兩個(gè)類GerneralUnit和GerneralUnitManage。

3.2通用實(shí)體類?

??? 下面是對(duì)通用實(shí)體類的定義:?

public abstract class GerneralUnit {//通用實(shí)體類?

? protected Hashtable attributes = null;//實(shí)體的特征(屬性-屬性值)存儲(chǔ)在哈希表中?

? protected String unitName = null;//實(shí)體(表)名?

? protected Hashtable field_type =null;//(屬性—屬性類型)?

? public abstract String getStringAttribute(String fieldName);//取某個(gè)String類型的屬性值,屬性名作為方法的參數(shù)?

? public abstract void setStringAttribute(String fieldName,String value);//設(shè)置某個(gè)String類型的屬性值,屬性名作為方法的參數(shù)?

? ...?

}?

??? 通過(guò)這種方式,可以將實(shí)體的方法與數(shù)據(jù)庫(kù)的表的字段名動(dòng)態(tài)地關(guān)聯(lián)起來(lái),其中一個(gè)好處就是避免了2節(jié)中的問(wèn)題②③,實(shí)體的方法不會(huì)隨著關(guān)系表的增長(zhǎng)而增長(zhǎng),其變動(dòng)對(duì)實(shí)體類的定義沒(méi)有影響。更重要的一個(gè)好處是這種動(dòng)態(tài)關(guān)聯(lián)使得該實(shí)體類成為通用的實(shí)體類,這個(gè)通用實(shí)體類可以隨關(guān)系表的不同,可能代表“學(xué)生類”、“教師類”、“課程類”、“工資類”等等,解決了問(wèn)題①。?

3.3通用實(shí)體管理類?

??? 下面是對(duì)通用實(shí)體管理類的定義:?

public class GerneralUnitManage {//通用實(shí)體管理類?

? //通過(guò)實(shí)體主特征查找實(shí)體,并返回動(dòng)態(tài)創(chuàng)建的實(shí)體對(duì)象?

? public GerneralUnit[] getUnits(String unitName,Hashtable mainAttribute){…}?

? public deleteUnit(String _UnitName,Hashtable mainAttribute){…}?

...?

}?

??? 在實(shí)體管理類的方法中,對(duì)數(shù)據(jù)庫(kù)的操作基本上分為兩種情況:一種是從數(shù)據(jù)庫(kù)關(guān)系表中取數(shù)據(jù),并根據(jù)這些數(shù)據(jù)為實(shí)體屬性賦值;另一種是根據(jù)實(shí)體的屬性值對(duì)關(guān)系表的記錄進(jìn)行添加、修改或刪除。通用性是通過(guò)獲取數(shù)據(jù)庫(kù)中表及其字段的相應(yīng)信息,并根據(jù)這些信息動(dòng)態(tài)賦予實(shí)體相應(yīng)屬性值(或根據(jù)動(dòng)態(tài)賦予實(shí)體的屬性值來(lái)進(jìn)行相應(yīng)的數(shù)據(jù)庫(kù)操作)來(lái)實(shí)現(xiàn)的。下面以GerneralUnitManage類中的查找實(shí)體方法getUnit為例進(jìn)行說(shuō)明:?

public GerneralUnit[] getUnits(String unitName,Hashtable mainAttribute) {//參數(shù):實(shí)體名、關(guān)鍵特征?

…?

? String strSQL = "select ZDMC, SJLX, ZDHY from VVVV where BMCV='" + unitName + "'";//查找關(guān)系表的所有字段?

? while(rs.next()) {?

??? String key = rs.getString("ZDMC");//將實(shí)體與關(guān)系表關(guān)聯(lián)起來(lái)?

??? …?

??? info.setAttributeType(key,dataType);?

??? …?

}?

String findSQL =…//根據(jù)查找實(shí)體屬性生成SQL語(yǔ)句?

ResultSet rs = stmt.executeQuery(findSQL);//執(zhí)行生成的SQL語(yǔ)句,根據(jù)結(jié)果集生成相應(yīng)實(shí)體?

while(rs.next()){?

? ??…?

??? for (i = 0; i < count; i ++ ) {//為實(shí)體賦予屬性值?

????????????? key = keysInDb.get(i).toString();?

????????????? unit.setAttribute(key, rs.getObject(key));?

??????????????????????? ? units.add(unit);?

??? }?

}?

… ?

if(bSuccessToGet)return units;?

else return null;?

}?

??? 因?yàn)槟軐?shí)體和關(guān)系表動(dòng)態(tài)關(guān)聯(lián),該實(shí)體管理類具有通用性。通過(guò)對(duì)其方法中的參數(shù)設(shè)置將不同的關(guān)系表與通用實(shí)體類關(guān)聯(lián)起來(lái),從而避免了2節(jié)中提到的類的數(shù)量隨數(shù)據(jù)庫(kù)中關(guān)系表的數(shù)量正比增長(zhǎng)的問(wèn)題。?

該方案是針對(duì)一般情況而設(shè)計(jì)的。對(duì)于某些特殊應(yīng)用,可以將上述通用方案的某些方法進(jìn)行重載以滿足部分特殊需求。?

4?結(jié)束語(yǔ)?

??? 本文針對(duì)面向?qū)ο蟮年P(guān)系數(shù)據(jù)庫(kù)數(shù)據(jù)訪問(wèn)實(shí)現(xiàn)中存在的問(wèn)題,提出了一種新的通用方案。應(yīng)用該方案可以一次性編寫兩個(gè)通用的類代替原來(lái)的諸多實(shí)體類和實(shí)體管理類,代碼量大大減少。并且這兩個(gè)類可以幾乎無(wú)需修改地應(yīng)用到其他系統(tǒng)中。該方案已經(jīng)在多個(gè)軍隊(duì)自動(dòng)化系統(tǒng)的開發(fā)中得到實(shí)際應(yīng)用。雖然本文是以三層結(jié)構(gòu)模型下的信息系統(tǒng)開發(fā)為例進(jìn)行說(shuō)明的,但是該方案對(duì)兩層結(jié)構(gòu)模型下的開發(fā)也有一定的借鑒意義。

參考文獻(xiàn)?

1、? 唐潛、楊德華,用JAVA類封裝RDB庫(kù)表──在關(guān)系數(shù)據(jù)庫(kù)上運(yùn)用OO技術(shù)探討,計(jì)算機(jī)應(yīng)用研究,1999.11

2、? Scott W. Ambler,Mapping objects to relational databases,http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index_eng.shtml,2000.7

3、? 王建華等譯,最新Java2核心技術(shù)(卷Ⅱ:高級(jí)性能),機(jī)械工業(yè)出版社,2003.1

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無(wú)法一一聯(lián)系確認(rèn)版權(quán)者。如涉及作品內(nèi)容、版權(quán)和其它問(wèn)題,請(qǐng)及時(shí)通過(guò)電子郵件或電話通知我們,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話:010-82306118;郵箱:aet@chinaaet.com。

相關(guān)內(nèi)容