段強(qiáng)
湘西農(nóng)副產(chǎn)品網(wǎng)絡(luò)平臺(tái)這個(gè)項(xiàng)目初期是作為一個(gè)中小型的垂直行業(yè)電子商務(wù)平臺(tái)而進(jìn)行設(shè)計(jì)的,但是在項(xiàng)目的設(shè)計(jì)需求中明確提出了要考慮到日后要能方便升級(jí)為大型的網(wǎng)絡(luò)平臺(tái),同時(shí)在系統(tǒng)架構(gòu)的概念性設(shè)計(jì)中也特別關(guān)注了這個(gè)問題。因此后續(xù)的開發(fā)工作中,在對(duì)數(shù)據(jù)層的設(shè)計(jì)上,我們細(xì)化出了一個(gè)在數(shù)據(jù)庫層之上的一個(gè)持久層來處理。
一、為何選用持久層
持久層是實(shí)現(xiàn)數(shù)據(jù)持久化的一個(gè)邏輯上的層次。數(shù)據(jù)持久化就是對(duì)系統(tǒng)中的數(shù)據(jù)固化到硬盤等物理存儲(chǔ)器中的一個(gè)過程。最大眾化的情況,就是通過某些程序設(shè)計(jì)語言把從軟件界面取得的數(shù)據(jù)保存到數(shù)據(jù)庫中的一個(gè)過程。
使用數(shù)據(jù)庫對(duì)數(shù)據(jù)進(jìn)行管理,效率最高的方法就是直接使用SQL語句。但是在主流的OOP編程語言平臺(tái)中,都不可避免地會(huì)把SQL語言和編程語言混雜在一起,即使程序員經(jīng)過了精心設(shè)計(jì),也依舊如此。本項(xiàng)目計(jì)劃使用JAVA作為開發(fā)平臺(tái),同樣面臨相同的情況。但是這樣的做法,在提高了軟件效率的同時(shí),卻犧牲了軟件的可修改性,尤其是在數(shù)據(jù)庫層更新為大型數(shù)據(jù)庫或分布式數(shù)據(jù)庫時(shí),需要重新編寫的代碼將不亞于重新開發(fā)所需要的代碼量。
二、如何設(shè)計(jì)持久層
在使用JAVA開發(fā)的軟項(xiàng)目中,其業(yè)務(wù)對(duì)象大體上可以分成普通的Java對(duì)象和持久對(duì)象。普通的Java對(duì)象用于控制、邏輯處理等業(yè)務(wù),而持久對(duì)象則用于對(duì)數(shù)據(jù)庫中的數(shù)據(jù)實(shí)體進(jìn)行映射。從功能上說,如果要在數(shù)據(jù)庫中插入一條記錄,則大致等同于將一個(gè)持久對(duì)象進(jìn)行初始化,而在數(shù)據(jù)庫中刪除一條記錄,則等同于將這個(gè)持久對(duì)象賦值為NULL,且清理內(nèi)存??梢哉f,數(shù)據(jù)持久化之后的結(jié)果是數(shù)據(jù)庫中存在真實(shí)的數(shù)據(jù)記錄,而數(shù)據(jù)持久層中的數(shù)據(jù)則是存儲(chǔ)在可掉電設(shè)備(例如內(nèi)存)中的對(duì)應(yīng)數(shù)據(jù)庫中數(shù)據(jù)的一些映射。
在代碼編寫階段,最原始的使用持久層的技術(shù)就是一些簡(jiǎn)單的代碼編寫工作,但是在企業(yè)級(jí)的開發(fā)中,就必須將對(duì)象-關(guān)系的映射(Object-Relation Mapping,ORM)框架與持久層的開發(fā)結(jié)合起來考慮了。
在本系統(tǒng)的設(shè)計(jì)中,出于對(duì)高可修改性的需求的滿足來考慮,我們對(duì)數(shù)據(jù)的處理采取了以下幾個(gè)步驟:1、使用DAO設(shè)計(jì)模式將底層的數(shù)據(jù)庫訪問和高層的業(yè)務(wù)邏輯分離,利用DAO模式提供的接口實(shí)現(xiàn)對(duì)數(shù)據(jù)庫的查詢、刪除等操作;2、采用工廠方法(Factory Method)設(shè)計(jì)模式設(shè)計(jì)類和接口,并實(shí)現(xiàn)系統(tǒng)接口來實(shí)現(xiàn)底層對(duì)象的訪問;3、充分利用面向?qū)ο蟪绦蛟O(shè)計(jì)中的繼承的概念,設(shè)計(jì)各種持久對(duì)象的子類,以便方便地將數(shù)據(jù)庫中的各種表中的記錄轉(zhuǎn)換為各種值對(duì)象來訪問。
就目前預(yù)期的系統(tǒng)使用而言,以上3個(gè)步驟的設(shè)計(jì)和實(shí)現(xiàn)完全依靠手工編寫代碼是綽綽有余了。可是倘若本軟件系統(tǒng)日后的數(shù)據(jù)庫處理需求升級(jí)或功能需求進(jìn)行了拓展后,我們將無法避免DAO模式中對(duì)于1對(duì)多(1:N)關(guān)系處理的弊端:對(duì)于1:N關(guān)系的持久對(duì)象的查詢隨著數(shù)據(jù)的拓展變成了1+N次SQL語句的執(zhí)行,直接導(dǎo)致代碼的出現(xiàn)大量的重復(fù)執(zhí)行,最終將導(dǎo)致系統(tǒng)可修改性完全喪失。這就不得不讓我們選擇一個(gè)較為可行的開發(fā)框架作為我們數(shù)據(jù)持久層設(shè)計(jì)的基礎(chǔ),其目的在于提高系統(tǒng)的可修改性。最終我們選定Hibernate作為本軟件系統(tǒng)持久層開發(fā)工具。
Hibernate的工作機(jī)制如圖1所示。使用Hibernate之后,編寫在業(yè)務(wù)邏輯層中的代碼通過Hibernate提供的API來操作數(shù)據(jù)這對(duì)代碼的編寫工作來說是相當(dāng)有利的。下面以用戶基本信息表中的部分信息為例,概要闡述如何應(yīng)用Hibernate設(shè)計(jì)一個(gè)持久化類,然后使用這個(gè)類的任意實(shí)例完成對(duì)應(yīng)的任務(wù)。創(chuàng)建最終用戶信息的持久化類時(shí),該類的屬性必須與數(shù)據(jù)庫中表的字段存在1:1的映射關(guān)系,還需要設(shè)置一個(gè)類似print()方法作為輸出的接口。在本例中,類的類圖如圖2所示。
類的設(shè)計(jì)完成后,需要在的是將數(shù)據(jù)庫中的表與這個(gè)類的對(duì)象產(chǎn)生聯(lián)系。為了實(shí)現(xiàn)這個(gè)目標(biāo),只需要編寫一個(gè)映射文件以實(shí)現(xiàn)數(shù)據(jù)庫中的數(shù)據(jù)和類的映射。之后繼續(xù)完成Hibernate的配置文件hibernate.cfg.xml中相應(yīng)的內(nèi)容即可。接下來是編寫Hibernate的配置文件hibernate.cfg.xml。該文件的部分內(nèi)容如表5.2所示。
三、如何應(yīng)用持久層的設(shè)計(jì)
在完成了以數(shù)據(jù)持久層的配置和設(shè)計(jì)工作以后,就可以專注于在建邏輯層中設(shè)計(jì)不同的類來實(shí)現(xiàn)各種功能了。例如,如果設(shè)計(jì)用戶注冊(cè)功能的類,其核心代碼如表1所示。
小結(jié):數(shù)據(jù)持久層的設(shè)計(jì)及其實(shí)現(xiàn)是有關(guān)系統(tǒng)效率、安全和可修改性等一系列質(zhì)量屬性優(yōu)劣與否的重要工作。在軟件架構(gòu)的概念設(shè)計(jì)中需要考慮這個(gè)問題,在軟件架構(gòu)的實(shí)際設(shè)計(jì)中需要在技術(shù)選型、開發(fā)平臺(tái)等技術(shù)細(xì)節(jié)中對(duì)此設(shè)計(jì)予以實(shí)現(xiàn)。但是這仍然是粗粒度的設(shè)計(jì),但是已經(jīng)可以為具體完成代碼編寫的工作人員提供開發(fā)依據(jù)了。