葛 萌,歐陽宏基,陳 偉
(咸陽師范學院 計算機學院,咸陽 712099)
數據持久化能夠提供獲取和長久保存數據的能力,采用合適的持久化技術構建性能良好、易于擴展和維護的持久化層是各類應用系統設計中必須考慮的重要問題之一.在以Java EE 技術為平臺的應用中存在著兩種主要的數據持久化解決方案:一種以SQL 技術為基礎,代表是JDBC和MyBatis 框架[1,2];另一種是以對象/關系映射(ORM)技術為基礎,代表是Hibernate 框架[3].Hibernate是對JDBC 的輕量級封裝,以面向對象的域模型為基礎,通過配置文件或注解自動實現POJO 對象與數據庫表的映射,避免傳統方式的建庫、建表、設置主外鍵等關系操作[4].但是MyBatis和Hibernate都是在設計模式+Java 反射機制基礎上形成的第三方框架,其學習成本較高,對開發人員具有較高的素質要求,尤其Hibernate 框架如果使用不當,在頻繁訪問數據庫、并發量大的場景下,會出現嚴重的性能問題.JDBC通過SQL 語句直接操作數據庫,相對于ORM 缺少了“翻譯”過程,經過精心設計與優化后,具有較高的執行效率.但是,傳統的JDBC也存在缺陷:需要考慮數據庫底層細節、業務邏輯與持久化邏輯高度耦合、相似持久化邏輯的代碼冗余度較高、在出現網絡故障的情況下,需要人工重啟Web 容器來解決數據庫連接對象失效等問題.
近年來已有不少學者針對上述問題進行了相關研究,主要集中在JDBC 基本理論、復用性、訪問效率等方面.文獻[5,6]主要研究了JDBC 訪問數據庫的一般算法和事務控制,分析了JDBC與ODBC 的區別.文獻[7]從策略模式和模板模式入手對JDBC 進行了改進,并以改進后的JDBC 設計了某電信客戶關系管理系統的數據持久層.文獻[8]針對JDBC 中的Connection對象在網絡環境異常情況下無法自動重連的問題,利用循環檢測方法提出一種Connection 自動連接策略.文獻[9,10]從多方面研究了JDBC 的緩存方案,提高了數據庫訪問效率.
本文針對傳統JDBC 存在的不足,在前人研究基礎上,綜合應用單例模式、模板模式、策略模式、DAO模式、工廠模式和配置文件,并在數據庫驅動加載過程中引入重連機制,在DAO 工廠中增加緩存機制,對JDBC 進行了改進.并以改進的JDBC 框架為基礎,完成了某高校績效考核管理系統持久層的設計與開發.并為以JDBC 作為數據持久化技術的Java EE 應用系統的開發提供了一定的參考.
JDBC是Java EE 應用中用來訪問關系型數據庫的一組API.主要包括:JDBC API、驅動管理器、JDBC驅動程序以及驅動程序的注冊機制[11].其中,開發人員使用JDBC API 訪問數據庫;數據庫廠商提供JDBC驅動程序;驅動管理器負責加載驅動程序,在JDBC API和驅動程序之間形成一個中轉,允許JDBC API 通過驅動程序來操作關系型數據庫,如圖1所示.

圖1 JDBC 體系結構
JDBC API 通過提供的幾個核心接口供開發人員使用,主要是Connection、Statement、PreparedStatemnt、CallableStatement和ResultSet.Connection 代表應用程序與數據庫之間的連接,是創建其它JDBC 接口的基礎并處理數據庫事務.Statement 用于執行普通的SQL語句.PreparedStatement是Statement 的子接口,能夠對SQL 語句進行預編譯并檢查語法錯誤,對于相同SQL 語句的多次執行能夠提高效率.CallableStatement是PreparedStatement 的子接口,用于執行數據庫端的存儲過程.ResultSet 用來封裝查詢語句所返回的結果集,并提供了對結果集進行遍歷、訪問和定位的相關方法.上述各接口的使用步驟是:① 通過反射機制加載驅動程序;② 由DriverManager 根據所訪問數據庫的URL、用戶名和密碼創建Connection 對象;③ 根據SQL語句所訪問的對象,由Connection 創建不同的Statement對象;④ 相關Statement 對象負責執行具體的SQL 語句,并處理執行的結果;⑤ 釋放相關資源.
JDBC 通過提供相關接口的方式,有效地在執行過程中明確了責任,屏蔽了各具體關系型數據庫的差異,降低了應用程序與數據庫的耦合度.由于持久化邏輯具有相似但又不完全相同的特點,相似性表現在任何一個持久化操作都要經過上述的5 個步驟;不同性表現在具體執行的SQL 語句和處理結果不同.所以傳統JDBC 存在著一些缺陷:不同實體對象的持久化操作具有很大的相似性,如果不進行封裝,會導致代碼冗余度高,復用率低;業務邏輯與持久化邏輯耦合度高,存在一些不必要的重復性操作(例如驅動程序的多次加載等);數據庫的改變需要修改源代碼,包括數據庫驅動獲取、連接配置和SQL 語句等部分,違背了“開-閉”原則.
本文針對傳統JDBC 框架存在的復用性低、耦合度高、不易移植等缺陷,設計了改進的JDBC 框架,通過DAO 模式向業務邏輯層提供調用持久化邏輯的接口,解耦合業務邏輯與持久化邏輯;利用模板、策略和工廠模式封裝DAO 的具體實現,實現具體持久化代碼的統一性并減少代碼的冗余度;利用XML+Property 配置文件來描述數據庫配置、DAO 配置、SQL 語句等信息,實現代碼的調優和解耦.改進的JDBC 框架如圖2所示.

圖2 改進的JDBC 框架
設計模式是在特定背景下,解決某個問題的最佳實踐,具體表現為一組精心設計的接口與類的組合[12,13].在編碼中應用設計模式能夠確保可重用性、可靠性,并易于被別人理解.根據模式的目的,一共分為:創建型、結構型和行為型3 類.其中,工廠模式屬于創建型模式,用于將對象的創建和使用相分離,在該JDBC框架中用于生成DAO和具體策略對象.DAO 模式作為業務邏組建訪問數據持久層的入口,屏蔽數據持久化的細節.模板方法模式屬于行為型,用于定義一個操作步驟的骨架,將其中可變的操作延遲到子類中完成.在改進的JDBC 框架中,將執行SQL 操作這個步驟延遲到子類完成.策略模式屬于行為型,通常定義一個算法族,由子類實現每個具體的算法并相互之間能夠轉換.在改進的JDBC 框架中,將Connection 對象的創建和資源釋放這兩個操作由策略模式實現,其中一個具體策略是通過傳統的DriverManager 獲取,資源釋放方式是銷毀;另一個具體策略是通過數據庫連接池獲取Connection,資源釋放是交回給連接池.綜合應用上述設計模式對JDBC 框架進行改進,可以把持久化操作中相似的功能進行封裝,進一步分離業務邏輯和持久化邏輯,使業務邏輯層和持久化層的耦合度進一步降低,提高代碼復用率.
改進的JDBC 框架的調用時序圖如圖3所示.業務層組件通過DAOFactory和配置文件獲取對應實體的DAO 對象;DAO 對象中創建JDBCTemplate 對象,JDBCTemplate 對象通過策略工廠對象得到JDBCStrategy對象,在創建過程中需要策略接口和配置文件的幫助;并且JDBCTemplate 封裝了JDBC 操作的公共邏輯,在JDBCStrategy 對象的配合下完成對數據庫的訪問,并將操作結果返回給業務層組件.

圖3 改進JDBC 框架的執行過程
以下給出改進的JDBC 框架在高校績效考核管理系統中的應用實例.系統環境是Window Server 2012作為服務器,MyEclipse16.1是集成開發工具,數據庫服務器是MySQL5.7.
采用績效考核系統對高校人員進行量化評價是采用信息化手段進行人力資源管理的一種變革,能夠使每位人員得到公正、公平的考評結果,為提高教學質量、工作效率,并為學校領導層提供正確的決策數據.系統的考核對象主要分為:教師系列、行政人員系列和工程實驗技術人員系列.以教師系列為例,實際的考核流程如圖4所示.

圖4 績效考核工作流程
首先由各二級學院布置年度考核工作安排,教師按照年度制定的目標責任書中的內容,逐條將自己相關的內容錄入系統.然后各二級學院召開考核評議會,由業務考評組根據考核內容進行量化打分,按照統計分數進行排名并定性評價.在此基礎上劃分優、良、合格和不合格比例.考核小組在院系內公布考核結果,如有異議,教師在三日內到院系考核小組進行復審.以院系為單位將教師考核相關匯總資料報送教務處和科技處,最后由教務處將各院系考核材料報送學校考核工作委員會審核,最終確定各教師本年度績效考核成績.
定義JDBCStrategy 作為抽象策略接口,包括獲取連接和釋放資源兩個操作.DBPoolStrategy和DMStrategy是兩個具體策略類.在單元測試階段使用DMStrategy策略,因為它不需要Web 容器的支持,可以提高測試效率.DBPoolStrategy 用在整體測試和項目運行階段,它以JNDI 方式獲取連接和回收資源[14].該策略需要在Web 服務器中配置數據庫連接池,因為連接池方式能夠對Connection 進行復用,避免反復創建和釋放連接對象而造成的性能消耗.DMStrategy 通過驅動管理者類獲取連接和釋放資源.這兩個策略類在獲取連接對象時都加入了數據庫重連機制.以DMStrategy 策略為例,在一個while 循環中通過DriverManager 獲取Connection.如果發生異常就讓當前線程對象休息一段時間后重新獲取Connection 對象,直到獲取成功就退出循環,這樣就可以避免重啟Web 服務器或應用程序所帶來的麻煩.
具體策略類利用靜態代碼段加載JDBC 驅動,避免了傳統方式中多次加載的弊端,提高了執行效率.數據庫驅動名稱、URL、用戶名和密碼等信息都寫在了DBConfig.properties 配置文件中,數據庫的變更不用修改具體策略類代碼,便于系統的移植.FileUtil 類采用單例模式來實現,用來把配置文件中的<K,V>鍵值信息保存到靜態的Properties 對象中,便于在具體策略類和工廠類中共享.
JDBCStrategyFactory是策略工廠,根據配置文件來創建不同的具體策略對象.具體策略切換時,只需要修改配置文件中的值,工廠類的代碼不需任何改動;當增加新的連接獲取方式時,只需要定義具體的策略類,原有的代碼不需要任何修改,很好的滿足了“開-閉”原則.
定義JDBCTemplate 作為模板封裝數據表通用的增、刪、改、查方法,利用關聯的工廠對象獲取具體策略,利用RowObjMapper 接口中的rowObjMapping()方法將查詢結果集轉換為實體對象.以find()方法為例,相關代碼如下所示.


利用DAO 模式將業務邏輯與持久化邏輯解耦.DAO 接口定義相關實體對象的持久化方法,DAOImp實現DAO與RowObjMapper 接口,通過關聯的JDBCTemplate 完成持久化操作.為了進一步解耦SQL語句與Java 代碼,將DAO 對應的SQL 語句寫到Peroperty 類型的配置文件中,如果出現持久化邏輯錯誤只需修改配置文件即可.
通過上述設計,改進后的JDBC 框架將傳統JDBC操作中的加載驅動、創建連接、創建Statement 對象和釋放資源等操作交由JDBCStratey、JDBCTemplate和RowObjMapper 完成,開發人員只需專注DAO 的開發.從而能夠降低持久化代碼的編寫量,提高開發效率.
分別使用傳統JDBC和改進的JDBC 對績效考評系統中的持久化層代碼進行設計,采用JUnit 框架測試持久化層代碼的執行時間,并統計出各自代碼的復用情況,具體數據見表1.

表1 JDBC 持久層代碼復用與執行時間對比圖
執行時間是指從業務邏輯層調用持久層代碼的執行時間,分別調用1 次和調用100 次,執行5 次取平均值.可以看出在單次執行的情況下,改進的JDBC 執行時間較長,開銷主要在兩個方面:① 設計模式增加了對象的調用開銷;② 工廠對象要解析并讀取配置文件.在多次調用的情況下,改進的JDBC 節省了執行時間,主要是因為:① 傳統JDBC 會多次加載驅動,改進的JDBC 只加載一次;② 改進的JDBC 在DAO 工廠中增加了緩存機制.由此可見,改進的JDBC 不但降低了時間復雜度,并且有效提高了代碼的復用率.
JDBC是目前Java EE 應用中數據持久化操作的一種常見解決方案,針對傳統JDBC 存在的缺陷,將策略模式、工廠模式、模板模式和數據庫重連機制對傳統JDBC 進行了改進,并成功地將改進的JDBC 框架應用于某高校績效考核系統的數據持久層設計中.通過項目實踐表明改進的JDBC 框架能夠提高數據持久層的開發效率和可復用率,降低了與業務邏輯層和數據持久層的耦合性,為Java EE 數據庫持久層的設計與開發提供了相應的借鑒.