歐陽宏基,葛 萌
(咸陽師范學院 計算機學院,咸陽 712000)
數(shù)據(jù)初始化是任何一個應用系統(tǒng)運行其業(yè)務邏輯的基礎.初始化的數(shù)據(jù)一般都是基礎數(shù)據(jù),由當前應用系統(tǒng)的需求分析而確定.一部分數(shù)據(jù)需要自行定義,一部分可能來自于和當前系統(tǒng)相關的其他業(yè)務系統(tǒng).初始化的數(shù)據(jù)通常在系統(tǒng)正式上線運行前或者運行時添加到數(shù)據(jù)庫中,是應用系統(tǒng)中其他業(yè)務數(shù)據(jù)賴以生存的前提,因此每一個系統(tǒng)都必須執(zhí)行數(shù)據(jù)初始化的操作.目前,常見的數(shù)據(jù)初始化操作方法有兩種:一種是為系統(tǒng)各模塊提供數(shù)據(jù)添加操作,通過用戶手工方式逐條錄入所需要的數(shù)據(jù),該方法適合規(guī)模較小、基礎數(shù)據(jù)量少的系統(tǒng)[1].第二種方法是通過數(shù)據(jù)庫第三方工具(例如MySQL 數(shù)據(jù)庫的SQLyog、Navicat 等)將存儲在Excel、XML、HTML 等文件中或者是其他信息系統(tǒng)數(shù)據(jù)庫中的相關數(shù)據(jù)批量導入到當前應用中,該方法適合規(guī)模、數(shù)據(jù)量較大的系統(tǒng),但是在操作過程中也必須單表逐個導入.無論采用上述哪種方法,用戶在操作時必須按照一定的順序,尤其是基礎數(shù)據(jù)之間存在較復雜依賴關系的請求下,無疑增加了用戶操作的復雜度,影響了用戶的操作體驗.
針對上述問題,在研究建造者模式、策略模式以及單例模式的前提下,提出一種新的數(shù)據(jù)初始化方法,該方法在系統(tǒng)運行前自動讀取存儲在外部相關文件中的數(shù)據(jù)并保存到當前應用的數(shù)據(jù)庫中,避免了手動操作的繁瑣.以高等院校目標考核管理系統(tǒng)中的數(shù)據(jù)初始化操作為例,分析了各部分的初始化數(shù)據(jù)以及順序問題.以Excel 文件作為數(shù)據(jù)初始化前的載體,利用JXL、JDBC 和Hibernate 作為混合數(shù)據(jù)持久化技術完成了數(shù)據(jù)的初始化操作,詳細闡述了上述各設計模式的具體實現(xiàn)過程,為數(shù)據(jù)初始化操作提供了一定的參考.
設計模式(design pattern)是面向?qū)ο蠹夹g中被精心編制的接口與類的組合,在特定的應用場景中使用特定的模式可以獲得結構清晰、易于擴展和理解的代碼結構[2,3].建造者模式(Builder Pattern)屬于創(chuàng)建型模式的一種,主要用于將一個復雜對象的構建與它的表示分離,向用戶屏蔽復雜對象組成部分的創(chuàng)建細節(jié)[4].單例模式(singleton pattern)也屬于創(chuàng)建型模式,主要用于約束某個類的對象只能被實例化一次.策略模式(strategy pattern)屬于行為型模式,該模式通常將某個行為的不同實現(xiàn)方式定義為某個單獨的類,允許調(diào)用端根據(jù)特定情況更換行為的實現(xiàn)方式[5].
基于Java EE 平臺的應用系統(tǒng)通常利用JDBC 或Hibernate 技術進行關系型數(shù)據(jù)庫的訪問.JDBC 通過Connection、Statement、ResultSet 等接口執(zhí)行原生SQL 語句操作數(shù)據(jù)庫[6];Hibernate 是ORM 協(xié)議的具體實現(xiàn),對JDBC 進行了輕量級封裝,以映射文件或注解為基礎實現(xiàn)對象模型與數(shù)據(jù)庫表的映射,并且自動管理對象與對象之間的關聯(lián)關系[7].Hibernate 提供了Configuration、SessionFactory、Session、Transaction和Query 和Criteria 等6 個核心接口對持久化對象進行存儲和事務控制,交互過程如圖1所示.其中,Configuration 負責讀取配置文件并創(chuàng)建SessionFactory;SessionFactory 是重量級組件采用了單例設計模式,在啟動時創(chuàng)建全局唯一對象并常駐內(nèi)容,主要用來管理Session 對象和部分緩存數(shù)據(jù).Session 對象代表了一條與數(shù)據(jù)庫的連接,用來創(chuàng)建Query 或Criteria 對象.Query 或Criteria 負責執(zhí)行HQL 語句,在Transaction 的管理下利用映射文件實現(xiàn)持久化對象與數(shù)據(jù)庫的交互[8].
圖1 Hibernate 核心接口交互圖
Java EE 應用的初始化過程中會涉及眾多的對象,他們之間必然存在復雜的關聯(lián)關系.通過ORM 將這些對象保存到數(shù)據(jù)庫中,并維持之間的外鍵關系,就必須考慮初始化的順序問題.例如在采用BRAC 模型實現(xiàn)的權限管理系統(tǒng)中,權限、角色和用戶三者存在著關聯(lián)關系[9].角色關聯(lián)權限,用戶關聯(lián)角色,首先應初始化權限數(shù)據(jù),再初始化角色數(shù)據(jù),最后初始化用戶數(shù)據(jù).因此,當對象的關聯(lián)關系之間具有先后順序時,需要先保存被關聯(lián)的對象數(shù)據(jù).
綜合應用單例、建造者、策略設計模式的數(shù)據(jù)初始化模型類圖關系如圖2所示.其中,SysData、SysData Builder、SysDataExcelBuilder 和SysDataDirector構成建造者模式.SysData 表示產(chǎn)品,定義所有要初始化的數(shù)據(jù);SysDataBuilder 表示抽象建造者,SysData ExcelBuilder 表示具體建造者;SysDataDirector 表示指揮者,其中的construct()方法控制初始化數(shù)據(jù)的順序.JDBCUtil 為單例設計模式,該類的主要作用有兩個,①封裝加載數(shù)據(jù)庫驅(qū)動、創(chuàng)建數(shù)據(jù)庫連接和釋放資源;② 創(chuàng)建和刪除數(shù)據(jù)庫.SysInit、InitStrategy 和ConcreteStrategy 構成策略模式.SysInit 為環(huán)境類、InitStrategy 為策略接口,ConcreteStrategy 為具體初始化策略,包括開發(fā)階段的初始化策略和系統(tǒng)部署上線運行階段的策略.
圖2 數(shù)據(jù)初始化方法類圖
目標考核系統(tǒng)是采用計算機與網(wǎng)絡技術所實現(xiàn)的對高校各部門年度目標任務進行信息化管理的Web 系統(tǒng).系統(tǒng)基于Java EE 平臺,采用MVC 模式設計,由Struts2+Spring+Hibernate 輕量級框架構建[10].核心功能包括目標任務的編制、任務的下達、任務完成數(shù)據(jù)的上傳、任務完成數(shù)據(jù)的審核、量化打分以及匯總等功能.通過該系統(tǒng)實現(xiàn)了目標考核工作的數(shù)字化管理,提高了考核過程的透明度、結果的公平性和公正性,對全校教職工的工作具有良好的引導和激勵作用,為學校領導層作決策提供了數(shù)據(jù)支撐.
由于目標考核工作涉及較多的職能部門(發(fā)展規(guī)劃處、人事處、科技處、學生工作處、教務處、學科辦、團委、黨委組織部、黨委宣傳部等)、各二級教學單位和全體教職工.考核目標覆蓋了教育教學、科學研究、師資隊伍建設、學生工作、黨風廉政建設等各個方面,因此系統(tǒng)運行所需要的基礎數(shù)據(jù)較多.按照考核工作的職責、對象和任務,將基礎數(shù)據(jù)劃分為三大部分,包括:用戶數(shù)據(jù)、權限數(shù)據(jù)和指標數(shù)據(jù).其中用戶數(shù)據(jù)包含技術職務、黨政職務、黨政職務級別、崗位級別、部門、教工基本信息、部門賬戶和科研類別.權限數(shù)據(jù)包括權限和角色.指標包括綜合指標和業(yè)務指標兩部分,每部分又細分為一級指標、二級指標和三級指標.其中一個一級指標包含多個二級指標,一個二級指標包含多個三級指標.上述各項數(shù)據(jù)的具體初始化先后順序依次是:技術職務、黨政職務、黨政職務級別、崗位級別、部門、權限、角色、教工基本信息、部門賬戶、科研級別、一級綜合指標、二級綜合指標、三級綜合指標、業(yè)績一級指標、二級業(yè)績指標、三級業(yè)績指標.
建造者設計模式包括抽象建造者、具體建造者、指揮者和產(chǎn)品4 個角色,如圖3所示.將目標考核系統(tǒng)的所有要初始化的數(shù)據(jù)看作一個整體,充當其中的產(chǎn)品角色,每個部分的數(shù)據(jù)作為產(chǎn)品的一個成員,用List集合表示,因此產(chǎn)品是一個較復雜的POJO 對象.抽象建造者角色關聯(lián)一個受保護的產(chǎn)品對象,定義初始化各部分數(shù)據(jù)的抽象接口,其中每一個buildXXX()方法創(chuàng)建一類要初始化的數(shù)據(jù),通過getResult()方法得到所關聯(lián)的產(chǎn)品對象.具體建造者繼承抽象建造者實現(xiàn)每一個buildXXX()方法,定義每一類數(shù)據(jù)的初始化邏輯.
圖3 建造者設計模式類圖
本文所實現(xiàn)的目標考核系統(tǒng)的初始化數(shù)據(jù)存儲在Excel 文件中,所以定義SysDataExcelBuilder 類作為具體的建造者.其中包含每一類初始化數(shù)據(jù)對應的Service 組件作為屬性,其對象通過@Resource 注解從Spring IOC 容器獲取.Service 對象通過@Resource 注解關聯(lián)的Dao 對象完成初始化操作,Dao 對象封裝了Hibernate API 具體負責初始化數(shù)據(jù)的增、刪、改、查操作.具體建造者通過讀取applicationContext.xml 文件創(chuàng)建Spring IOC 容器,用ApplicationContext 對象表示.另外還包含一個InputStream 對象用作讀取Excel 文件的流對象,一個Workbook 對象用來表示Excel 的工作表,通過JXL 完成對Excel 工作表和單元格數(shù)據(jù)的訪問[11].
策略設計模式包括環(huán)境、抽象策略和具體策略三個角色,如圖4所示.該模式可以根據(jù)環(huán)境或者條件的不同而選擇不同的策略來完成某項任務.InitStrategy為抽象策略接口,其中initData 方法定義數(shù)據(jù)初始化算法.DevelopmentStrategy 和RunningStratey 是兩個具體的初始化策略,DevelopmentStrategy 是系統(tǒng)開發(fā)階段使用的策略,具體的數(shù)據(jù)初始化算法是如果數(shù)據(jù)庫存在先刪除數(shù)據(jù)庫,再創(chuàng)建數(shù)據(jù)庫并通過建造者模式的指揮者對象調(diào)用初始化操作.RunningStrategy 是系統(tǒng)部署上線運行時采用的策略,具體的數(shù)據(jù)初始化算法是獲取初始化完成標記信息,判斷是否已經(jīng)執(zhí)行過初始化操作,如果已經(jīng)執(zhí)行則忽略;如果沒有初始化過,那么先創(chuàng)建數(shù)據(jù)庫,通過建造者模式的指揮者對象調(diào)用初始化操作并設置初始化完成標記,標記信息存儲在特定數(shù)據(jù)庫表中.
圖4 策略設計模式類圖
單例設計模式能夠確保某個類只能擁有自己的一個對象,在某些工具類的定義中普遍應用單例模式.這種工具類基本上貫穿程序始終,必然會頻繁調(diào)用.如果每一次調(diào)用都要重新生成實例,帶來的就是內(nèi)存堆空間的浪費,所以單例模式能夠提高程序的運行速度,減少資源消耗.文獻[12]分析了單例模式實現(xiàn)的5 種方式,總結了每種方式的優(yōu)缺點和應用場景.本初始化模型在操作數(shù)據(jù)庫時采用JDBC 與Hibernate 相結合的混合持久化技術,所以采用靜態(tài)內(nèi)部類方式作為單例模式的實現(xiàn)方法,因為該方法具有調(diào)用效率高、線程安全、支持延遲加載等優(yōu)點.
由于Hibernate 框架能夠創(chuàng)建并更改數(shù)據(jù)庫表結構,實現(xiàn)對象與表、對象之間關系與表之間關聯(lián)的映射,但無法自動創(chuàng)建數(shù)據(jù)庫,因此需要通過JDBC 執(zhí)行SQL 自動創(chuàng)建數(shù)據(jù)庫.利用單例模式定義JDBCUtil,用來封裝JDBC 的加載數(shù)據(jù)庫驅(qū)動、獲取Connection對象和釋放資源等3 個操作,這個單例對象作為JDBC操作的全局唯一入口.同樣為了簡化Hibernate進行持久化操作代碼的重復性,利用單例模式定義HibernateUtil,該類完成對Hibernate 有關代碼的封裝,其中包含的主要操作有g e t S e s s i o n F a c t o r y()、getSession()和closeSession().在各部分初始化數(shù)據(jù)對應的泛型DAO 實現(xiàn)類中對HibernateUtil 單例對象進行調(diào)用,完成公共的save()、delete()、update()、getById()、getByIds()和findAll()方法的邏輯.
系統(tǒng)實施所采用的相關工具信息如表1所示.
表1 系統(tǒng)相關工具信息表
要導入到系統(tǒng)中的初始化數(shù)據(jù)存放在Excel 文件中,共包括16 張worksheet,其中技術職務表有數(shù)據(jù)52 條、黨政職務類別表有數(shù)據(jù)6 條、黨政職務名稱表28條、崗位類別表4條、部門信息表48條、權限數(shù)據(jù)表126 條、角色表有27 條、部門賬戶表有60 條、教工信息表1248 條、科研級別表47條、一級指標表5條、二級指標表30條、三級指標表109 條、業(yè)績一級指標表6條、業(yè)績二級指標表23條、業(yè)績?nèi)壷笜吮?7條,文件總大小為680 KB.進行開發(fā)階段的策略測試時,在JUnit 單元測試中調(diào)用初始化數(shù)據(jù)的代碼,如下代碼所示:
執(zhí)行后發(fā)現(xiàn)在MySQL 中生成了對應的數(shù)據(jù)庫以及相應的表,每個表中都插入了對應Excel 工作表中的數(shù)據(jù).第二次再執(zhí)行會先刪除上次創(chuàng)建的數(shù)據(jù)庫,再重新生成數(shù)據(jù)庫及對應的表.多次測試后平均完成初始化操作的時間為195s.針對運行時策略的測試,由于運行時策略在系統(tǒng)正式部署時使用,所以定義了初始化監(jiān)聽器執(zhí)行上述代碼,將具體策略換成RunningStrategy.初始化監(jiān)聽器在web.xml 中的配置位置位于Spring IOC 容器的配置后,因為只有Spring 容器初始化后,才能通過容器對象得到各部分初始化數(shù)據(jù)對應的Service 組件.經(jīng)過測試,初始化操作會在Web 服務器啟動后自動執(zhí)行,以后再次啟動Web 服務器初始化操作不再執(zhí)行.
設計模式是面向?qū)ο蟪绦蛟O計中通用問題的一種可復用解決方案.將建造者、策略和單例模式應用到基礎數(shù)據(jù)的初始化設計中,簡化了初始化操作.同時,應用系統(tǒng)如需增加其他初始化數(shù)據(jù),只需更改產(chǎn)品、抽象建造者和具體建造者角色;如果需要從其他存儲方式中讀取初始化數(shù)據(jù),只需重新定義具體建造者角色.因此,所提出的數(shù)據(jù)初始化方法具有較高的復用性、維護性和擴展性.