歐陽宏基, 葛萌, 程海波
(咸陽師范學院, 計算機學院, 陜西, 咸陽 712000)
JDBC是JavaEE平臺中用來訪問關系型數據庫的原生API[1],它存在若干缺點:頻繁進行Connection對象的創建和銷毀,影響數據庫性能;將SQL語句硬編碼到Java代碼中,導致SQL語句的修改,要重新編譯Java代碼;將PreparedStatement對象中的占位符參數硬編碼到Java代碼中,不利于系統維護;從結果集遍歷數據時,需要編寫數據表字段與對象屬性的映射邏輯。
針對上述缺點,本文提出基于MyBatis框架的數據庫持久層設計方案。首先分析了MyBatis框架的核心組件與執行流程,闡述了MyBatis實現DAO的兩種方案并分析了優缺點,結合目標考核管理系統持久層的部分業務邏輯詳細描述了MyBatis的應用過程,為數據持久層的開發提供了一定的借鑒。
MyBatis對JDBC 進行了二次封裝,能夠與第三方數據庫連接池集成,實現Connection對象的復用[2]。MyBatis使開發人員將主要精力放在編寫SQL語句上,通過映射方式,半自動化地生成持久化代碼。通過輸入映射自動完成向preparedStatement中輸入參數,通過輸出映射自動將結果集映射成Java對象[3],實現了Java代碼與JDBC API的解耦。使得開發人員無須花精力去處理諸如注冊驅動、創建Connection、創建Statement、手動設置參數、結果集檢索等繁瑣的操作。
MyBatis的核心組件包括以下部分[4],結構如圖1所示。

圖1 MyBatis框架核心組件
(1) 核心配置文件:它是MyBatis的全局配置文件,主要完成數據源、事務處理、延遲加載、緩存和加載映射文件等配置。
(2) 映射文件(mapper.xml):定義操作數據庫的SQL語句,實現輸入映射和輸出映射。
(3) SqlSessionFactory(會話工廠):根據配置文件由SqlSessionFactoryBuilder創建會話工廠,從而創建SqlSession對象。
(4) SqlSession:定義了一組數據庫操作的API。
(5) Executor:它是SqlSession內部真正操作數據庫的對象。根據SqlSession傳遞的參數動態地生成需要執行的SQL語句,同時負責查詢緩存的維護。
(6) MappedStatement:對映射信息進行封裝,用于存儲要映射的SQL語句的id、參數等。
MyBatis的執行流程如圖2所示。首先通過流加載核心配置文件,然后將流對象注入SqlSessionFactoryBuilder對象用于創建SqlSessionFactory對象,從SqlSessionFactory 對象中獲取SqlSession,利用SqlSession的selectOne()、selectList()、insert()、 update()、delete()等方法操作數據庫,最后關閉SqlSession對象。

圖2 MyBatis框架的執行流程
數據持久層在Java EE中主要用來為業務邏輯層提供訪問數據源的接口,封裝操作數據源的邏輯和相關API,完成實體對象與數據庫表的映射。普遍采用DAO設計模式來封裝數據持久層的代碼[5]。所以,MyBatis框架完成數據持久層開發主要就是實現DAO,如圖3所示。MyBatis提供了兩種實現DAO的方式:一種是傳統DAO的實現方式,需要編寫DAO接口、DAO的實現類、實體類和映射文件,在DAO實現類中調用MyBatis的API操作數據庫;另一種實現方式是采用動態代理技術自動生成DAO 實現類的對象,開發人員只需編寫DAO接口、實體類和映射文件,不需要編寫DAO的實現類,通過SqlSession的getMapper()方法就能自動生成DAO實現類的對象。相比傳統DAO的實現方式,此方式無需編寫調用MyBatis API操作數據庫的代碼,能夠提高數據持久層的開發效率。

圖3 MyBatis開發持久層示意圖
高等院校目標考核管理系統是在高校多職能部門的配合下采用信息化手段進行人力資源管理的一個應用軟件[6]。其功能模塊包括:基礎數據維護、教工信息管理、指標管理、信息查詢、系統維護等[7]。用戶角色包括:教工、各職能部門管理員、系統管理員、校領導。系統基于MVC模式、采用Java EE分層架構模型[8-9],數據持久層利用MyBatis框架進行設計與開發。
定義mybatis-config.xml作為核心配置文件,利用C3P0數據庫連接池作為數據源。首先通過〈properties〉標簽的resource屬性加載C3P0.properties文件,該文件定義了數據庫驅動、URL、用戶名、密碼、數據庫連接池配置參數等信息。然后通過〈environments〉標簽定義數據源,通過OGNL表達式讀取C3P0.properties文件中的值。采用JDBC的事務管理,由MyBatis控制事務。通過〈settings〉標簽進行全局參數配置,包括延遲加載和二級緩存。通過〈typeAliases〉標簽以批量方式為POJO類定義別名。最后通過〈mappers〉標簽來加載映射文件。
采用動態代理生成DAO實現類的方式作為持久層的開發方法。首先要定義DAO接口(Mapper接口),其中定義與實體類或角色對應的持久化方法。目標考核系統持久層一共定義了TeacherMapper.java、PaperMapper.java、TaskDetailMapper. java等53個Mapper接口。以系統中校領導角色為例,對應的Mapper接口中與查詢科研數據有關的部分源碼如下:
public interface XLDMapper{
public List〈Papaer〉 findPaper(PaperDTO paperDTO) throws Exception;
public List〈Patent〉 findPatent(PatentDTO patentDTO) throws Exception;
…………
}
定義實體類與數據庫表進行映射,其中的屬性包括兩類:一類是與表字段一一對應的基本屬性;另一類是在聯合查詢中定義所關聯的對象或對象集合。方法包括設置和獲取屬性的setter和getter方法。目標考核系統中所包含的實體類有:UserInfo、Teacher、Department、Role、Permission、Paper、ScientificProject、Patent、Monograph、Student、IndexLevelOne、IndexLevelTwo、IndexLevelThree等53個。
相對于原生JDBC,MyBatis框架將SQL語句轉移到映射文件中定義,實現了與Java代碼的解耦合。因此,編寫映射文件是使用MyBatis框架的核心內容。映射文件中主要定義與Mapper接口中方法一一對應的Statement,主要包括Statement ID、SQL語句、輸入映射和輸出映射。其中,〈insert〉、〈delete〉、〈update〉和〈select〉標簽分別定義數據庫的增、刪、改和查詢操作。輸入映射定義對應SQL語句所需要的參數,輸出映射定義SQL語句所返回的數據類型。MyBatis在執行數據庫操作時會把Statement解析成一條具體的SQL,將輸入映射類型中的數據替換SQL語句中的?占位符,將執行結果轉換成輸出映射對應的Java數據類型。
以XLDMapper.xml為例,它是XLDMapper.java接口對應的映射文件。其中,findPaper()方法的邏輯是按照年份、學院、職稱等條件相組合來查詢發表的論文數據。PapaerDTO表示論文信息的數據傳輸對象,是輸入映射的POJO類型,該類封裝了查詢語句需要的參數信息,具體包括UserInfo實體類、Department實體類和年份。執行結果轉換成Paper類型,它是論文信息的實體類。考慮到用戶在頁面所選查詢條件的不同,需要根據不同查詢條件來動態拼接SQL語句。
持久層的Mapper接口和映射文件定義完成后需要在JUnit中進行單體測試,確保邏輯正確后才能供業務層組件調用。將MyBatis操作數據庫的共性步驟封裝到工具類中,這樣可以避免冗余代碼。定義MyBatisUtil工具類將加載配置文件、創建SqlSessionFactory、創建SqlSession、釋放資源等操作進行封裝,并且確保SqlSessionFactory是一個單例對象[10]。
數據持久層在Java EE分層架構中占據著舉足輕重的地位,穩定、高效的持久層開發方案一直是JavaEE應用開發的重點。本文提出了基于MyBatis框架的數據持久層應用開發方法,并成功應用到目標考核管理系統數據持久層的設計與實現中。MyBatis框架通過映射文件分離了Java代碼與SQL語句,通過輸入映射、輸出映射以及DAO的動態生成等功能簡化了代碼編寫量,提高了數據持久層的開發效率。