摘 要: 數(shù)據(jù)持久層在Web應(yīng)用系統(tǒng)開(kāi)發(fā)中,主要應(yīng)用于業(yè)務(wù)邏輯和數(shù)據(jù)邏輯的松散耦合,提高軟件可重用性。分析了Hibernate框架及DAO設(shè)計(jì)模式的工作原理,設(shè)計(jì)了基于Hibernate框架采用DAO設(shè)計(jì)模式的數(shù)據(jù)持久層架構(gòu)體系,并通過(guò)具體Web應(yīng)用,闡述了數(shù)據(jù)持久層架構(gòu)的具體實(shí)現(xiàn)過(guò)程。
關(guān)鍵詞: 數(shù)據(jù)持久化;Hibernate框架;DAO模式;O/R映射
在Web應(yīng)用系統(tǒng)中,Web服務(wù)器作為連接客戶(hù)端和數(shù)據(jù)庫(kù)服務(wù)器的一個(gè)中間層,既要對(duì)客戶(hù)端提出的請(qǐng)求進(jìn)行業(yè)務(wù)分析和處理,又要訪問(wèn)數(shù)據(jù)庫(kù)并與數(shù)據(jù)庫(kù)進(jìn)行交互。當(dāng)業(yè)務(wù)邏輯代碼中包含數(shù)據(jù)訪問(wèn)代碼時(shí),將給系統(tǒng)的修改和維護(hù)帶來(lái)很大困難,同時(shí)也不利于以后在開(kāi)發(fā)類(lèi)似系統(tǒng)中進(jìn)行大粒度的軟件重用。因此有必要把功能層劃分為業(yè)務(wù)邏輯層和持久層。業(yè)務(wù)邏輯層專(zhuān)注于業(yè)務(wù)邏輯的分析和處理,持久層專(zhuān)注于與數(shù)據(jù)庫(kù)交互進(jìn)行數(shù)據(jù)的持久化工作,并提供一個(gè)標(biāo)準(zhǔn)的接口供業(yè)務(wù)邏輯層調(diào)用。通過(guò)這樣一個(gè)層次的劃分,實(shí)現(xiàn)了高效、清晰的專(zhuān)業(yè)分工和職責(zé)劃分,既實(shí)現(xiàn)了功能層中業(yè)務(wù)邏輯和數(shù)據(jù)邏輯之間的松耦合關(guān)系,又利于系統(tǒng)的修改、維護(hù)和軟件重用[1]。
目前的J2EE應(yīng)用系統(tǒng)開(kāi)發(fā)中已經(jīng)存在不少框架。在系統(tǒng)架構(gòu)分析時(shí),如何應(yīng)用已有框架為應(yīng)用系統(tǒng)量身定做一個(gè)合適的架構(gòu),對(duì)J2EE設(shè)計(jì)開(kāi)發(fā)者提出了挑戰(zhàn)。本文基于Hibernate框架采用DAO設(shè)計(jì)模式,設(shè)計(jì)了數(shù)據(jù)持久層架構(gòu)。并將其應(yīng)用于問(wèn)卷調(diào)查系統(tǒng),實(shí)現(xiàn)了業(yè)務(wù)邏輯和數(shù)據(jù)邏輯的松散耦合,提高了系統(tǒng)的開(kāi)發(fā)效率和軟件重用性。
1 Hibernate技術(shù)
1.1 Hibernate框架
Hibernate是采用ORM映射機(jī)制進(jìn)行持久層數(shù)據(jù)開(kāi)發(fā)的工具,它是Java應(yīng)用程序和關(guān)系數(shù)據(jù)庫(kù)中間的橋梁,負(fù)責(zé)對(duì)Java對(duì)象和關(guān)系型數(shù)據(jù)之間映射[2]。其架構(gòu)體系如圖1所示。
Hibernate內(nèi)部封裝JDBC進(jìn)行訪問(wèn)數(shù)據(jù)庫(kù)操作,其向上層應(yīng)用對(duì)象提供面向?qū)ο蟮臄?shù)據(jù)庫(kù)訪問(wèn)API,使開(kāi)發(fā)者能充分運(yùn)用面向?qū)ο蟮木幊趟季S操作數(shù)據(jù)庫(kù),而無(wú)需關(guān)心底層數(shù)據(jù)庫(kù)操作。Hibernate自身通過(guò)hibernate.cfg.xml和類(lèi)的映射文件將類(lèi)和數(shù)據(jù)庫(kù)相映射,應(yīng)用程序通過(guò)Hibernate及持久化對(duì)象類(lèi)直接訪問(wèn)底層數(shù)據(jù)庫(kù)。
1.2 Hibernate核心接口
利用Hibernate進(jìn)行數(shù)據(jù)持久化操作,至少會(huì)用到下列核心接口:Configuration接口負(fù)責(zé)配置啟動(dòng)Hibernate并創(chuàng)建SessionFactory對(duì)象;SessionFactory接口產(chǎn)生Session實(shí)例的工廠類(lèi),負(fù)責(zé)初始化Hibernate并創(chuàng)建Session對(duì)象;Session接口是Hibernate進(jìn)行持久化操作的基礎(chǔ),相當(dāng)于JDBC中的Connection對(duì)象所起的作用。Session提供了一系列的持久化操作方法,如保存、更新、刪除、查詢(xún)等;Transaction接口負(fù)責(zé)管理事務(wù);Query和 Criteria接口負(fù)責(zé)執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)[3]。
2 DAO設(shè)計(jì)模式
DAO(Data Access Object)模式稱(chēng)為數(shù)據(jù)訪問(wèn)對(duì)象模式,是Java EE核心模式之一,其主要的功能是在業(yè)務(wù)核心方法和具體數(shù)據(jù)源之間再增加一層DAO接口及其實(shí)現(xiàn)類(lèi)。該模式的本質(zhì)是向外部提供一個(gè)訪問(wèn)數(shù)據(jù)源的統(tǒng)一接口,對(duì)外隱藏操作數(shù)據(jù)源的實(shí)現(xiàn)細(xì)節(jié),以此實(shí)現(xiàn)業(yè)務(wù)邏輯層與DB的解耦[4]。這是因?yàn)樵趯?shí)際的應(yīng)用過(guò)程中,應(yīng)用程序所面對(duì)的數(shù)據(jù)源往往是多種多樣的,不同數(shù)據(jù)源的連接方式、數(shù)據(jù)訪問(wèn)方式會(huì)有明顯差異,導(dǎo)致了需要訪問(wèn)數(shù)據(jù)源的組件的代碼實(shí)現(xiàn)方式與數(shù)據(jù)源的類(lèi)型有著密切的關(guān)系,組件和數(shù)據(jù)源之間的這種緊耦合關(guān)系也就導(dǎo)致了整個(gè)應(yīng)用系統(tǒng)難以在不同數(shù)據(jù)源之間進(jìn)行遷移。使用了DAO模式后,即使系統(tǒng)需要進(jìn)行數(shù)據(jù)源的遷移,也只需在DAO模式內(nèi)部進(jìn)行數(shù)據(jù)源訪問(wèn)代碼的修改,而不會(huì)涉及上層調(diào)用代碼,從而提高了軟件可維護(hù)性。
3 數(shù)據(jù)持久層架構(gòu)設(shè)計(jì)及實(shí)現(xiàn)
3.1 數(shù)據(jù)持久層框架設(shè)計(jì)
在應(yīng)用程序和數(shù)據(jù)庫(kù)之間構(gòu)建數(shù)據(jù)持久層,可降低J2EE應(yīng)用與數(shù)據(jù)庫(kù)的耦合度,并簡(jiǎn)化程序開(kāi)發(fā)。基于Hibernate框架采用DAO模式設(shè)計(jì)的數(shù)據(jù)持久層整體架構(gòu)如圖2所示。
業(yè)務(wù)邏輯是整個(gè)框架的業(yè)務(wù)處理的核心部分,由業(yè)務(wù)邏輯接口、接口實(shí)現(xiàn)類(lèi)和配置文件等組成。它接收控制層的各類(lèi)調(diào)用請(qǐng)求,控制著系統(tǒng)邏輯的實(shí)現(xiàn)和處理,并通過(guò)調(diào)用數(shù)據(jù)持久層的DAO接口完成數(shù)據(jù)的存取操作。業(yè)務(wù)邏輯接口向控制層或其他業(yè)務(wù)邏輯接口實(shí)現(xiàn)類(lèi)提供各種業(yè)務(wù)邏輯接口方法,接口實(shí)現(xiàn)類(lèi)則對(duì)這些己定義的接口進(jìn)行具體實(shí)現(xiàn)。
數(shù)據(jù)持久層使用DAO來(lái)抽象和封裝所有對(duì)數(shù)據(jù)源的訪問(wèn),DAO管理著數(shù)據(jù)源的連接以便檢索和存儲(chǔ)數(shù)據(jù),DAO通過(guò)DAO工廠管理,DAO工廠負(fù)責(zé)生成DAO組件實(shí)例,并維護(hù)DAO實(shí)例;業(yè)務(wù)邏輯組件不與DAO組件的實(shí)現(xiàn)類(lèi)耦合,只與DAO組件的接口耦合;DAO實(shí)現(xiàn)類(lèi)中封裝Hibernate API來(lái)完成與持久化類(lèi)相關(guān)的業(yè)務(wù)邏輯操作。
Hibernate配置文件的主要工作是進(jìn)行SessionFactory配置、關(guān)系型數(shù)據(jù)庫(kù)“方言”與加載持久化類(lèi)對(duì)應(yīng)的映射文件等。映射文件用來(lái)聲明Hibernate中持久化類(lèi)的屬性與數(shù)據(jù)庫(kù)對(duì)應(yīng)表之間字段的映射關(guān)系。
數(shù)據(jù)持久化層架構(gòu)的操作流程為:業(yè)務(wù)邏輯模塊調(diào)用DAOFactory,DAOFactory生成相應(yīng)的DAO接口及實(shí)現(xiàn)類(lèi),DAO實(shí)現(xiàn)類(lèi)中封裝Hibernate API來(lái)訪問(wèn)持久化類(lèi),通過(guò)O/R映射文件聲明持久化類(lèi)與關(guān)系數(shù)據(jù)庫(kù)的映射,最終實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的操作。
3.2 數(shù)據(jù)持久層框架的應(yīng)用——解決方案及實(shí)現(xiàn)
本設(shè)計(jì)的數(shù)據(jù)持久層架構(gòu),作為數(shù)據(jù)持久層解決方案應(yīng)用于問(wèn)卷調(diào)查系統(tǒng),最大限度地降低了系統(tǒng)內(nèi)部各模塊、子系統(tǒng)之間的耦合性,保證了持久層的業(yè)務(wù)邏輯層相對(duì)穩(wěn)定,基本不需要持久層的調(diào)整改變而進(jìn)行邏輯層的變動(dòng)。問(wèn)卷調(diào)查系統(tǒng)由問(wèn)題管理、問(wèn)卷管理、統(tǒng)計(jì)管理、用戶(hù)管理、學(xué)生信息管理等模塊構(gòu)成,其數(shù)據(jù)持久層的具體組織結(jié)構(gòu)如圖3所示[5]。
4 數(shù)據(jù)持久層的實(shí)現(xiàn)
4.1 持久化類(lèi)及對(duì)象/關(guān)系映射文件
4.1.1 持久化類(lèi)
持久化類(lèi)的對(duì)象PO(Persistenct Object)是一個(gè)簡(jiǎn)單 Java對(duì)象(POJO),一個(gè)PO代表了與數(shù)據(jù)庫(kù)表中某條記錄相對(duì)應(yīng)的Hibernate實(shí)體,PO的變化在事務(wù)提交時(shí)反映到實(shí)際的數(shù)據(jù)庫(kù)表中。Hibernate中的持久化類(lèi)符合JavaBean的規(guī)范,包括一些屬性和對(duì)屬性的訪問(wèn)方法。圖4是問(wèn)卷調(diào)查系統(tǒng)中Question實(shí)體類(lèi)的模型圖[6]。可以看出,除了無(wú)意義的主屬性只能被獲取以外,每一個(gè)屬性都有被外部對(duì)象獲取(get)和設(shè)置(set)兩種方法,通過(guò)它們可以獲得對(duì)象的屬性值并實(shí)現(xiàn)對(duì)象之間的導(dǎo)航。
4.1.2 對(duì)象/關(guān)系映射文件
映射文件用一個(gè)XML格式的映射描述文檔來(lái)聲明Hibernate中持久化類(lèi)的屬性與數(shù)據(jù)庫(kù)對(duì)應(yīng)表之間字段的映射關(guān)系,該文件中聲明的屬性名稱(chēng)要與對(duì)應(yīng)數(shù)據(jù)表中的字段名稱(chēng)相同,同時(shí)也要與持久化類(lèi)中所包含的屬性名稱(chēng)相同。
4.2 Hibernate配置
為了用Hibernate進(jìn)行持久化實(shí)現(xiàn),還需要在應(yīng)用程序的包里放置一個(gè)配置文件,以便Hibernate能正確地完成數(shù)據(jù)庫(kù)連接等各種配置和初始化。由于映射文件可以在XML格式的配置文件中進(jìn)行聲明,在程序中不必調(diào)用Configuration類(lèi)的addClass方法來(lái)加載映射文件,因此這種格式的配置文件可以提高應(yīng)用程序的可維護(hù)性。
4.3 數(shù)據(jù)持久層的DAO接口及實(shí)現(xiàn)類(lèi)
數(shù)據(jù)持久化層采用Hibernate作為中間件,使用DAO設(shè)計(jì)模式實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)。DAO模式的實(shí)現(xiàn)包括DAO接口和DAO實(shí)現(xiàn)類(lèi)兩部分。DAO接口負(fù)責(zé)定義訪問(wèn)特定持久化類(lèi)所對(duì)應(yīng)的抽象業(yè)務(wù)邏輯方法;DAO實(shí)現(xiàn)類(lèi)負(fù)責(zé)利用Hibernate API實(shí)現(xiàn)DAO接口所定義的抽象方法的具體實(shí)現(xiàn)。
問(wèn)卷調(diào)查系統(tǒng)在實(shí)現(xiàn)DAO模式時(shí),首先創(chuàng)建了HibernateBasicDao,該類(lèi)繼承Spring框架提供的HibernateDaoSupport類(lèi),HibernateBasicDao類(lèi)封裝了對(duì)數(shù)據(jù)庫(kù)持久化的操作,任何它的子類(lèi)只要使用它的方法就可以實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的持久化操作。最后使每個(gè)DAO實(shí)現(xiàn)類(lèi)都繼承HibernateBasicDao類(lèi)實(shí)現(xiàn)數(shù)據(jù)庫(kù)的持久化操作。
圖5描述了問(wèn)題DAO接口及其實(shí)現(xiàn)類(lèi),它封裝了對(duì)問(wèn)題的基本操作。其中,delete方法刪除問(wèn)題信息,getQuestionById方法通過(guò)question的Id獲得,getQuestionInCurPape方法通過(guò)當(dāng)前頁(yè)數(shù)獲得question的具體類(lèi),query方法更新問(wèn)題信息等。限于篇幅,其他DAO接口及實(shí)現(xiàn)類(lèi)的設(shè)計(jì)不一一給出。
在基于J2EE的應(yīng)用中,系統(tǒng)的數(shù)據(jù)持久層代表著某個(gè)系統(tǒng)中一個(gè)相對(duì)獨(dú)立界限明確的邏輯層次,在這個(gè)層次中,將數(shù)據(jù)的使用者和數(shù)據(jù)實(shí)體相關(guān)聯(lián),負(fù)責(zé)對(duì)數(shù)據(jù)庫(kù)存儲(chǔ)數(shù)據(jù),同時(shí)也負(fù)責(zé)數(shù)據(jù)的檢索、更新和刪除,實(shí)現(xiàn)數(shù)據(jù)的讀取和持久化操作。本文運(yùn)用Hibernate框架技術(shù)設(shè)計(jì)了一套數(shù)據(jù)持久層架構(gòu)體系,并將其作為數(shù)據(jù)持久層解決方案應(yīng)用于問(wèn)卷調(diào)查系統(tǒng)。實(shí)踐結(jié)果表明,數(shù)據(jù)持久層架構(gòu)的應(yīng)用,降低了數(shù)據(jù)持久邏輯與業(yè)務(wù)邏輯的耦合度,簡(jiǎn)化了開(kāi)發(fā)過(guò)程,優(yōu)化了數(shù)據(jù)訪問(wèn)操作,增強(qiáng)了系統(tǒng)擴(kuò)展性和可維護(hù)性。
參考文獻(xiàn)
[1] 郭善飛.基于J2EE的數(shù)據(jù)持久層組件的設(shè)計(jì)與實(shí)現(xiàn)[D].北京:北京郵電大學(xué),2009.
[2] 張飛,張建.基于Spring與Hibernate的數(shù)據(jù)庫(kù)訪問(wèn)技術(shù)研究[J].計(jì)算機(jī)工程與設(shè)計(jì),2009,30(7):1669.
[3] 汪萌,曲俊華.基于Hibernate技術(shù)的持久層解決方案及實(shí)現(xiàn)[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2010,19(3):155.
[4] 歐陽(yáng)宏基.一種基于DAO設(shè)計(jì)模式與Hibernate框架的數(shù)據(jù)持久化層模型[J].微計(jì)算機(jī)應(yīng)用,2009,30(3):36-37.
[5] 嚴(yán)海.基于Struts+Spring+Hibernate框架構(gòu)建WEB應(yīng)用的設(shè)計(jì)與實(shí)現(xiàn)[D].西安:西安電子科技大學(xué).2010.
[6] 吳京慧.基于Hibernate對(duì)象持久化Web應(yīng)用的研究[J].計(jì)算機(jī)應(yīng)用與軟件,2009,26(2):90-91.