摘要:當(dāng)今大部分的應(yīng)用系統(tǒng)需要處理持久化數(shù)據(jù),而在使用面向?qū)ο蠹夹g(shù)開(kāi)發(fā)系統(tǒng)時(shí),會(huì)遇到對(duì)象持久化的問(wèn)題。同時(shí)使用關(guān)系數(shù)據(jù)庫(kù)存儲(chǔ)數(shù)據(jù),存在對(duì)象模型與關(guān)系模型之間的“阻抗不匹配”問(wèn)題。對(duì)廣泛使用的0/R映射框架Hibernate進(jìn)行研究,使用Hibernate作為業(yè)務(wù)邏輯層和數(shù)據(jù)庫(kù)層之間的持久層,實(shí)現(xiàn)對(duì)象到關(guān)系數(shù)據(jù)庫(kù)的持久存儲(chǔ)。結(jié)合實(shí)際應(yīng)用系統(tǒng)分析對(duì)象/關(guān)系映射在Hibernate持久化解決方案中的體現(xiàn)。
關(guān)鍵詞:對(duì)象持久化;持久層;對(duì)象/關(guān)系映射;Hibernate
中圖分類號(hào):TP311
文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1004-373X(2008)04-066-03
現(xiàn)今,面向?qū)ο箝_(kāi)發(fā)技術(shù)已經(jīng)普及到各種軟件開(kāi)發(fā)領(lǐng)域中,他是用符合事物本原與適應(yīng)人類自身思維方式的方法組織程序。面向?qū)ο蠹夹g(shù)是一種基于類和對(duì)象的應(yīng)用程序開(kāi)發(fā)技術(shù),程序員通過(guò)使用類和對(duì)象,以及對(duì)他們繼承、封裝等操作,可以方便地開(kāi)發(fā)出高質(zhì)量的應(yīng)用程序。同時(shí)當(dāng)前大多的應(yīng)用程序都使用關(guān)系數(shù)據(jù)庫(kù)作為數(shù)據(jù)的存儲(chǔ)機(jī)制。而面向?qū)ο蟮臋C(jī)制與關(guān)系模型有著很大的不同,他們之間存在阻抗不匹配(Impedance Mismatch)。面向?qū)ο笤O(shè)計(jì)基于軟件工程的一些原理如聚集、封裝等理論,其使用一組對(duì)象來(lái)完成任務(wù);而關(guān)系模型基于數(shù)學(xué)原理,尤其是集合論的原理。因此,需要一種映射方法解決這種不匹配,對(duì)象關(guān)系映射便隨之產(chǎn)生。把對(duì)表直接進(jìn)行的操作,變成對(duì)對(duì)象的屬性和方法的操作。Hibernate是一個(gè)基于Java的開(kāi)放源代碼的對(duì)象關(guān)系映射框架,他對(duì)JDBC做了輕量級(jí)的封裝。目前Hibernate已被廣泛使用,作為企業(yè)應(yīng)用和關(guān)系數(shù)據(jù)庫(kù)之間的中間件,以減輕和對(duì)象持久化有關(guān)的大量的JDBC編程工作。
1 對(duì)象持久化
1.1對(duì)象持久化的定義
在使用面向?qū)ο蠹夹g(shù)開(kāi)發(fā)應(yīng)用系統(tǒng)時(shí),系統(tǒng)運(yùn)行過(guò)程中構(gòu)造的對(duì)象實(shí)例,都是瞬時(shí)或暫時(shí)性的,叫作暫態(tài)對(duì)象或臨時(shí)對(duì)象;他存在于內(nèi)存之中,系統(tǒng)一旦停止運(yùn)行,這些對(duì)象都將消失,信息不復(fù)存在。因此,需要將對(duì)象實(shí)例長(zhǎng)期持久地保存,使之成為永久對(duì)象,這就是對(duì)象持久化。
1.2 實(shí)現(xiàn)對(duì)象持久化的方法
對(duì)象持久化技術(shù)是可以永久地存儲(chǔ)對(duì)象的方法,持久化機(jī)制包括基于操作系統(tǒng)的文件存儲(chǔ)、關(guān)系數(shù)據(jù)庫(kù)RDB和面向?qū)ο蟮臄?shù)據(jù)庫(kù)OODB等。目前大多使用關(guān)系數(shù)據(jù)庫(kù)作為對(duì)象持久化的存儲(chǔ)機(jī)制,采用關(guān)系數(shù)據(jù)庫(kù)實(shí)現(xiàn)對(duì)象持久化的方法主要有:內(nèi)嵌SQL語(yǔ)句、封裝成數(shù)據(jù)類以及使用對(duì)象持久層。
(1)內(nèi)嵌SQL語(yǔ)句:這種方法最為常見(jiàn),他是在類的源代碼中嵌入SQL語(yǔ)句。其優(yōu)點(diǎn)是編碼快捷,適用于小型應(yīng)用程序和原型模型中;缺點(diǎn)是難于維護(hù)和擴(kuò)展,數(shù)據(jù)庫(kù)的小變化(如:列的重新命名)也會(huì)導(dǎo)致源代碼的改寫(xiě)。模式圖如圖1所示。
(2)封裝成數(shù)據(jù)類:這種方法是將業(yè)務(wù)類里的SQL語(yǔ)句封裝到一個(gè)或幾個(gè)“數(shù)據(jù)類”里,例如存儲(chǔ)過(guò)程和EJB的實(shí)體Bean策略。這種方法適用于40~50個(gè)類的小型系統(tǒng)。但是當(dāng)數(shù)據(jù)庫(kù)發(fā)生簡(jiǎn)單變化時(shí),仍會(huì)導(dǎo)致數(shù)據(jù)類的重新編譯。模式圖如圖2所示:
(3)對(duì)象持久層:持久層是應(yīng)用程序與數(shù)據(jù)庫(kù)的隔離層,他封裝了與數(shù)據(jù)庫(kù)交互的底層細(xì)節(jié)。使用持久層時(shí)數(shù)據(jù)庫(kù)的簡(jiǎn)單改變不會(huì)影響面向?qū)ο蟮拇a。程序員只需管理和使用面向?qū)ο蟮臄?shù)據(jù),而不必關(guān)心數(shù)據(jù)存儲(chǔ)的底層實(shí)現(xiàn)細(xì)節(jié)。模式圖如圖3所示。
2 對(duì)象/關(guān)系映射
面向?qū)ο蟮臋C(jī)制與關(guān)系模型之間存在著阻抗不匹配,兩者有著不同的理論基礎(chǔ)。對(duì)象模型側(cè)重于使用包含數(shù)據(jù)和行為的對(duì)象來(lái)構(gòu)建應(yīng)用程序;而關(guān)系模型則主要針對(duì)于數(shù)據(jù)的存儲(chǔ)。兩種機(jī)制的不同使他們的結(jié)合并不理想。因此,需要一種映射方法來(lái)解決兩者之間的不匹配。這種方法就是對(duì)象關(guān)系映射0bject/Relational Mapping(O/RMapping)。
2.1對(duì)象/關(guān)系映射模式
在研究對(duì)象/關(guān)系映射的模式時(shí),通常采用如下的對(duì)應(yīng)關(guān)系將對(duì)象與數(shù)據(jù)表關(guān)聯(lián)起來(lái):
根據(jù)抽象對(duì)象與關(guān)系數(shù)據(jù)庫(kù)的特性,O/R Mapping在以下幾個(gè)方面實(shí)現(xiàn):
(1)從類屬性到數(shù)據(jù)表列的映射。類屬性和表列并非一一對(duì)應(yīng)。一個(gè)類屬性可對(duì)應(yīng)O或多個(gè)實(shí)體表的字段。在設(shè)置主鍵時(shí),通常采用無(wú)業(yè)務(wù)意義的字段對(duì)象標(biāo)識(shí)符(Object Identifier,OID)作為各個(gè)實(shí)體表的主鍵,OlD也作為類與數(shù)據(jù)庫(kù)映射時(shí)的對(duì)象的惟一標(biāo)識(shí)。
(2)從類到數(shù)據(jù)表的映射。當(dāng)不同層次的父類和子類映射到數(shù)據(jù)表時(shí),應(yīng)該根據(jù)實(shí)際的系統(tǒng)設(shè)計(jì)結(jié)果,權(quán)篌采用怎樣的映射策略。這種映射主要是指繼承映射,可以采用的映射策略主要分為以下3種:1個(gè)類繼承樹(shù)1個(gè)表、1個(gè)具體類1個(gè)表和1類1表。
(3)類間關(guān)系映射為鍵值。這是映射的難點(diǎn),主要是體現(xiàn)類關(guān)系中的關(guān)聯(lián)和聚集。關(guān)聯(lián)關(guān)系的映射中,一對(duì)一關(guān)聯(lián)、一對(duì)多關(guān)聯(lián)是通過(guò)在關(guān)聯(lián)的某一方引用對(duì)方的OIE實(shí)現(xiàn);多對(duì)多的關(guān)聯(lián)需要?jiǎng)?chuàng)建關(guān)聯(lián)表,或者劃分成一對(duì)多和多對(duì)一。聚集關(guān)系的映射有2種模式,分別是單表聚集模式和外鍵聚集模式。
2.2 對(duì)象/關(guān)系映射框架
如今常用的持久層框架有:EJB,JDO,Hibernate。Cas—tor和TopLink等。其中Hibernate是一個(gè)開(kāi)放源代碼的ORM框架,他給開(kāi)發(fā)者提供了一個(gè)強(qiáng)大而易用的O/R映射機(jī)制,得到了廣泛的應(yīng)用。
3 Hibernate
Hibernate是Gavin King于2001年開(kāi)始開(kāi)發(fā)的。他是一個(gè)基于Java的對(duì)象關(guān)系映射框架,對(duì)JDBC做了輕量級(jí)的封裝,以統(tǒng)一的接口方式支持多種數(shù)據(jù)庫(kù),具有豐富、詳細(xì)的參考文檔?,F(xiàn)在,越來(lái)越多的開(kāi)發(fā)人員把Hiber-nate作為企業(yè)應(yīng)用和關(guān)系數(shù)據(jù)庫(kù)之間的中間件。
3.1 Hibernate配置
使用Hibernate進(jìn)行對(duì)象的持久化,需要一個(gè)配置文件對(duì)Hibernate進(jìn)行配置和初始化。Hibernate有2種配置方式,分別是使用hibernate.properties文件和hiber-nate.cfg.xml文件,2種配置是一樣的。在配置文件中,可以配置數(shù)據(jù)庫(kù)的方言、連接驅(qū)動(dòng)類、用戶名及密碼和URL等。此外,使用hibernate.cfg.xml文件進(jìn)行配置時(shí)還可以指定mapping resource,在這里寫(xiě)入持久化類的映射文件(類名.hbm.xml)。
3.2持久化類
Hibernate創(chuàng)建和使用的持久化對(duì)象大多是一種叫作POJO(Plain Ordinary Java Objeet)的對(duì)象,從字面上來(lái)講就是無(wú)格式普通Java對(duì)象,可以簡(jiǎn)單地理解為一個(gè)不包含邏輯代碼的值對(duì)象(Value Objeet,VO)。
持久化類必須單獨(dú)定義一個(gè)主鍵ID,作為對(duì)象標(biāo)識(shí)符OlD。另外,每個(gè)屬性都要有與之對(duì)應(yīng)的getter和set—ter方法。
3.3 映射文件
每個(gè)持久化類都要有與之對(duì)應(yīng)的映射文件,映射文件名為“類名.hbm.xml”。這個(gè)映射文件定義O/R映射的規(guī)則。例如持久化類Person具有屬性ID和name,其映射文件Person.hbm.xml可以描述如下:
其中主鍵應(yīng)該用<id>描述,在該節(jié)點(diǎn)下用<genera—tor>節(jié)點(diǎn)聲明主鍵的生成策略,在使用中需根據(jù)實(shí)際需要選擇使用何種策略。
映射的內(nèi)容除了主鍵ID、一般屬性外,還包括繼承的映射、關(guān)聯(lián)的映射和組件的映射等。本文所涉及的賓館管理系統(tǒng)使用了其中的一些映射模式,其說(shuō)明如下:
(1)繼承的映射:對(duì)于有繼承關(guān)系的父類和子類的映射,只需建立父類的映射文件,然后在這個(gè)文件中描述子類的映射。繼承映射有3種映射策略,在Hibernate映射規(guī)則中都有相應(yīng)實(shí)現(xiàn),如可以使用“一個(gè)類繼承樹(shù)一個(gè)表”的映射策略l映射文件中使用
3.4持久化對(duì)象的操作
首先,映射文件要將持久化類映射到相應(yīng)的數(shù)據(jù)庫(kù)表,這里需要用Configuration類配置,并建立起映射關(guān)系,然后在這個(gè)配置基礎(chǔ)上建立一個(gè)會(huì)話工廠SessionFacto-
創(chuàng)建會(huì)話工廠后,就可以從中獲取會(huì)話Session,每次Session操作,代表應(yīng)用程序和持久層之間的一次對(duì)話,也就是1次數(shù)據(jù)處理。獲取Session后,可以對(duì)對(duì)象進(jìn)行保存、查詢、刪除和修改等操作。使用Hibernate提供的面向?qū)ο蟮牟樵冋Z(yǔ)言HQL(Hibernate Query Language),使得對(duì)對(duì)象的操作變得十分簡(jiǎn)單:
4 結(jié) 語(yǔ)
應(yīng)用對(duì)象持久層的開(kāi)發(fā)方法是一種完全面向?qū)ο蟮姆椒?,在該方法中,首先從?wèn)題域中抽象出類與對(duì)象;其次對(duì)于持久性對(duì)象,通過(guò)對(duì)象持久層實(shí)現(xiàn)其與存儲(chǔ)機(jī)制的交互。持久層框架已廣泛應(yīng)用于當(dāng)前的系統(tǒng)開(kāi)發(fā)中,使用成熟的持久層框架,能夠大大提高系統(tǒng)開(kāi)發(fā)的效率。Hibernate作為成功的持久層框架被廣泛使用,在應(yīng)用系統(tǒng)開(kāi)發(fā)中正在并繼續(xù)發(fā)揮重要的作用。