軟體項目實訓及課程設計指導——如何正確地設計J2EE應用系統持久層中的各個組件結構及關係
1、了解J2EE應用系統數據持久層中的各個組件類的類型
在J2EE系統平臺下的軟體應用系統的數據持久層,一般都包含有如下的各個組件類:實體類、數據訪問對象類(包括接口和對應的實現類)和數據連接類。如下示圖為體現持久層中的各個組件類相互關係的示例圖。
2、了解J2EE應用系統數據持久層中的各個組件類的類型和職責
(1)持久實體類(Persistant Object)
實體類一般實現對物理資料庫系統中的一個具體的資料庫表中的各個欄位數據的封裝,也就是該類的一個對象實例對應於物理資料庫系統的資料庫表中的一條記錄;實體類中的各個成員屬性與資料庫表中的欄位相互映射;在實體類中一般不提供功能方法。
1)實體類中的成員屬性和物理資料庫系統的資料庫表中的欄位是相互對應關係的映射,此種形式的實體類一般稱為域實體類(Domain Entity)。
2)實體類中的成員屬性也可以與物理資料庫系統的資料庫表中的欄位結構不完全產生出相互對應關係的映射,此種形式的實體類稱為用戶自定義實體類(Custom Entity)。
持久實體類對象實例的生命周期和物理資料庫系統連接的狀態密切相關——物理資料庫系統連接Connection對象被關閉以後,持久實體類對象實例也就不再存在。
作者註:
讀者應該要區分持久實體類(PO)和業務實體類(VO,Value Object,簡稱為值對象)之間的差別,VO的本質是業務對象,並且只存活在系統的業務層中,主要提供給系統的業務邏輯組件類程序使用。
(2)數據訪問邏輯組件(包括接口和對應的實現類)
數據訪問邏輯組件是一個無狀態的物理資料庫系統訪問功能操作類,調用之間不存在狀態之間的傳遞。在結構和功能設計方面的主要目標如下:
首先,數據訪問邏輯組件在結構設計方面要提供接口和對接口中定義的各個功能方法的實現類;
其次,數據訪問邏輯組件在接口內定義的各個功能方法主要要處理以下的數據訪問技術實現的細節和為上層的業務層組件提供對應的功能服務:
1)實現對目標資料庫表中數據的「增、刪、改和查」操作,這是其主要的功能實現的任務;
下圖所示為銀行帳戶管理系統中的帳戶DAO組件接口中的各個功能方法定義——這些功能方法主要是實現對銀行帳戶信息資料庫表中的數據進行各種形式的「增、刪、改、查」操作。
2)正確處理數據訪問的安全性和授權問題,避免關鍵性的數據被非法訪問和修改;
3)正確處理事務處理問題,以保證對數據訪問的一致性;
下圖所示為在銀行帳戶信息管理系統中的帳戶DAO組件的批處理刪除batchDeleteAccountInfo功能方法中應用事務控制的程序代碼片段圖示。當然,也可以應用面向切面AOP編程中所倡導的分離「核心功能」和「輔助功能」程序代碼的設計思想,將事務處理的程序代碼單獨封裝為一個組件類。
4)執行數據分頁查詢和顯示的邏輯,並優化數據訪問邏輯的實現以獲得最佳的數據訪問性能;
下圖所示為銀行帳戶信息管理系統中分頁顯示帳戶信息的效果圖,通過數據分頁顯示不僅可以提高數據訪問的效率、而且也使得目標數據的顯示頁面更加簡潔和清晰。
5)如果應用系統需要緩存以進一步提高數據訪問的性能,則還需要為非事務性數據的查詢實現緩存策略。
6)執行數據流加工和轉換、對數據進行序列化等方面的操作。
(3)資料庫連接功能實現類
為了在軟體應用系統後臺的物理資料庫系統的數據源發生變化的情況下,儘可能地減少對數據訪問對象功能類的代碼的改動。應該在軟體應用系統中提供一個資料庫連接類以封裝資料庫類型及對物理資料庫系統的連接方式的可能變化。
當然,為了提高軟體應用系統中的資料庫連接的效率,在設計方面一般都採用實現JDBC 2.0規範中的DataSource接口的資料庫連接池提供對物理資料庫系統的連接對象或者應用O/R Mapping類型的應用框架(如Hibernate框架、iBatis框架等)中所提供的數據連接組件,也可以應用第三方系統平臺所提供的DataSource實現(如Apache DBCP組件提供的DataSource實現)。
下圖所示為銀行帳戶信息管理系統中利用Apache DBCP資料庫連接池的實現組件為系統提供資料庫連接功能類的程序代碼片段局部示圖截圖——Apache DBCP是Apache Commons項目中的一個子項目,為J2EE技術平臺下的應用系統提供一種與應用伺服器無關的資料庫連接池實現方案,有助於應用系統的移植和功能擴展。
3、合理地設計和實現軟體應用系統數據持久層中的異常處理功能程序類
(1)合理地設計和實現數據持久層中的異常處理功能程序類
由於軟體應用系統數據持久層會涉及大量的對物理資料庫表中的數據的各種操作訪問,而JDBC API中的許多功能方法都有異常拋出的聲明。而且一旦數據訪問組件DAO中的某個功能方法拋出異常後,相關程序的執行流程將要發生改變。下圖所示為某個軟體應用系統在運行過程中直接拋出異常錯誤提示信息、並在瀏覽器中顯示輸出的局部截圖。
因此,軟體應用系統的設計人員對異常的正確處理是軟體應用系統設計和開發實現中極為重要的一個方面,對異常層次的合理劃分不僅提高了程序代碼的可維護性,而且也有利於開發過程中的程序調試、跟蹤相關程序代碼中的錯誤狀況、並快速地定位出錯誤的代碼位置。
(2)異常處理設計的基本原則
在處理軟體應用系統中的異常時,要注意不能讓最終的用戶看到原始的Java異常信息。因此,軟體應用系統的設計人員應該首先對原始的Java異常信息進行包裝,然後向最終用戶顯示出容易理解的錯誤信息或者將英文的錯誤提示翻譯為中文的錯誤提示,從而使得最終用戶更清晰地了解目前軟體應用系統的故障原因。
其次還應該將原始的Java異常信息記錄到系統日誌文件中,以幫助軟體應用系統的系統管理員或者軟體開發人員進一步查找錯誤的原因提供方便。下圖所示為銀行帳戶信息管理系統中,在AccountManageDAOJDBCImple程序類中的deleteOneAccountInfoPO方法中實現將原始的Java異常信息記錄到系統日誌文件中的程序代碼片段截圖。
最後在軟體應用系統表示層的相關組件中捕獲系統底層中各個功能組件所拋出的系統異常,然後顯示出與特定的應用邏輯相關的錯誤提示文字。下圖所示為銀行帳戶信息管理系統中,在AccountInfoManageAction的J2EE MVC Struts2應用框架的Action類中捕獲異常、並轉發到目標JSP頁面顯示輸出的程序代碼片段截圖。
4、有關數據訪問操作功能實現類中的事務控制的設計問題
(1)不應該將事務控制代碼直接寫在系統的業務邏輯層中
事務控制代碼到底是放在軟體應用系統的持久層中的DAO組件中還是放在系統上層的數據訪問服務層中的DAOService組件類中,這取決於系統中的數據訪問服務的「粒度」!
如果系統中的數據訪問服務只需要單個DAO組件中相關的功能方法,而且每個DAO組件都是基於對物理資料庫系統中的單一資料庫表操作,也就是系統中的數據訪問服務的「粒度」比較小,此時則應該將事務控制代碼放在DAO組件內。由於每個方法實現了一個特定的功能,也就是一個事務,那麼直接在方法開始啟動事務,方法結束提交事務就可以。
當然,如果系統中的數據訪問服務的「粒度」比較大,某個業務處理功能(如轉帳)需要多個相關的DAO組件中的方法相互配合才能完成,也就是說需要多個DAO組件內的方法在一個事務中執行,則應該將事務控制代碼放在系統服務層中的DAOService組件類程序中(需要將事務控制提到DAO組件外部)。因為,此時再將事務控制代碼如果放在DAO組件類程序中,則無法進行單一的事務控制、並且每個DAO組件中的功能方法都是單獨的一個資料庫連接Connection對象,一旦該方法執行結束,對物理資料庫系統連接的資料庫連接Connection對象就會被關閉。
當然,不應該將事務控制代碼直接寫在軟體應用系統的業務邏輯層中。如果採用這樣的設計方案,將導致軟體應用系統中的業務邏輯組件中包含有與業務無關的功能實現代碼,同時也造成了軟體應用系統中的業務層與持久層之間的緊密耦合關係。
此外,事務在設計方面除了要遵守事務所具有的原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)(簡稱為ACID)的要求以外,在事務劃分的設計方面,也還應該要遵守如下的基本設計原則:使事務儘可能短小,因此保持事務儘可能短小的最好方法當然是在事務處理中不做任何不必要耗費時間的事,特別是不要在事務中間等待用戶輸入。
(2)應用面向切面AOP編程思想分離數據訪問邏輯和事務控制邏輯的實現代碼
由於事務控制邏輯的實現代碼是與所採用的數據訪問實現技術緊密相關的,如JDBC 資料庫訪問API、基於O/R Mapping技術的Hibernate框架和Spring應用框架、J2EE JTA分布式事務等相關的實現技術中都分別提供各自的事務控制實現方法和對應的事務控制API。
因此,為了提供軟體應用系統中事務控制實現的可移植性,應該要應用面向切面AOP編程思想分離數據訪問邏輯和事務控制邏輯的實現代碼。
具體的功能程序的實現方式可以採用Java語言中的動態代理技術設計事務控制的通用代理類或者應用Spring框架中提供的聲明形式的事務控制實現技術。下圖所示是在銀行帳戶信息管理系統中的對前面示圖所示的事務控制實現代碼進行重構後的實現代碼,將事務控制實現代碼放到一個動態代理的程序類中。