學習筆記之什么是持久化和對象關系映射ORM技術
by Naven at 2005-09-19
何謂“持久化”
持久(Persistence),即把數據(如內存中的對象)保存到可永久保存的存儲設備中(如磁盤)。持久化的主要應用是將內存中的數據存儲在關系型的數據庫中,當然也可以存儲在磁盤文件中、XML數據文件中等等。
何謂“持久層”
持久層(Persistence Layer),即專注于實現數據持久化應用領域的某個特定系統的一個邏輯層面,將數據使用者和數據實體相關聯。
何謂“對象數據映射(ORM)”
ORM-Object/Relational Mapper,即“對象-關系型數據映射組件”。對于O/R,即 Object(對象)和 Relational(關系型數據),表示必須同時使用面向對象和關系型數據進行開發。
備注:建模領域中的 ORM 為 Object/Role Modeling(對象角色建模)。另外這里是“O/R Mapper”而非“O/R Mapping”。相對來講,O/R Mapping 描述的是一種設計思想或者實現機制,而 O/R Mapper指以O/R原理設計的持久化框架(Framework),包括 O/R機制還有 SQL自生成,事務處理,Cache管理等。
除了 ORM 技術,還有以下幾種持久化技術
主動域對象模式
它是在實現中封裝了關系數據模型和數據訪問細節的一種形式。在 J2EE 架構中,EJB 組件分為會話 EJB 和實體 EJB。會話 EJB 通常實現業務邏輯,而實體 EJB 表示業務實體。實體 EJB 又分為兩種:由 EJB 本身管理持久化,即 BMP(Bean-Managed Persistence);有 EJB 容器管理持久化,即 CMP(Container-Managed Persistence)。BM P就是主動域對象模式的一個例子,BMP 表示由實體 EJB 自身管理數據訪問細節。
主動域對象本身位于業務邏輯層,因此采用主動域對象模式時,整個應用仍然是三層應用結構,并沒有從業務邏輯層分離出獨立的持久化層。
JDO 模式
Java Data Objects(JDO)是 SUN 公司制定的描述對象持久化語義的標準API。嚴格的說,JDO 并不是對象-關系映射接口,因為它支持把對象持久化到任意一種存儲系統中,包括 關系數據庫、面向對象的數據庫、基于 XML 的數據庫,以及其他專有存儲系統。由于關系數據庫是目前最流行的存儲系統,許多 JDO 的實現都包含了對象-關系映射服務。
CMP 模式
在 J2EE 架構中,CMP(Container-Managed Persistence)表示由 EJB 容器來管理實體 EJB 的持久化,EJB 容器封裝了對象-關系的映射及數據訪問細節。CMP 和 ORM 的相似之處在于,兩者都提供對象-關系映射服務,都把對象持久化的任務從業務邏輯中分離出來。區別在于 CMP 負責持久化實體 EJB 組件,而 ORM 負責持久化 POJO,它是普通的基于 Java Bean 形式的實體域對象。
一般把基于 Java Bean 形式的實體域對象稱為 POJO(Plain Old Java Object),意為又普通又古老的 Java 對象的意思。隨著各種 ORM 映射工具的日趨成熟和流行,POJO有重現光彩,它和基于 CMP 的實體 EJB 相比,即簡單又具有很高的可移植性,因此聯合使用 ORM 映射工具和 POJO,已經成為一種越來越受歡迎的且用來取代 CMP 的持久化方案。POJO 的缺點就是無法做遠程調用,不支持分布式計算。
為什么要做持久化和ORM設計
在目前的企業應用系統設計中,MVC,即 Model(模型)- View(視圖)- Control(控制)為主要的系統架構模式。MVC 中的 Model 包含了復雜的業務邏輯和數據邏輯,以及數據存取機制(如 JDBC的連接、SQL生成和Statement創建、還有ResultSet結果集的讀取等)等。將這些復雜的業務邏輯和數據邏輯分離,以將系統的緊耦合關系轉化為松耦合關系(即解耦合),是降低系統耦合度迫切要做的,也是持久化要做的工作。MVC 模式實現了架構上將表現層(即View)和數據處理層(即Model)分離的解耦合,而持久化的設計則實現了數據處理層內部的業務邏輯和數據邏輯分離的解耦合。而 ORM 作為持久化設計中的最重要也最復雜的技術,也是目前業界熱點技術。
簡單來說,按通常的系統設計,使用 JDBC 操作數據庫,業務處理邏輯和數據存取邏輯是混雜在一起的。
一般基本都是如下幾個步驟:
1、建立數據庫連接,獲得 Connection 對象。
2、根據用戶的輸入組裝查詢 SQL 語句。
3、根據 SQL 語句建立 Statement 對象 或者 PreparedStatement 對象。
4、用 Connection 對象執行 SQL語句,獲得結果集 ResultSet 對象。
5、然后一條一條讀取結果集 ResultSet 對象中的數據。
6、根據讀取到的數據,按特定的業務邏輯進行計算。
7、根據計算得到的結果再組裝更新 SQL 語句。
8、再使用 Connection 對象執行更新 SQL 語句,以更新數據庫中的數據。
7、最后依次關閉各個 Statement 對象和 Connection 對象。
由上可看出代碼邏輯非常復雜,這還不包括某條語句執行失敗的處理邏輯。其中的業務處理邏輯和數據存取邏輯完全混雜在一塊。而一個完整的系統要包含成千上萬個這樣重復的而又混雜的處理過程,假如要對其中某些業務邏輯或者一些相關聯的業務流程做修改,要改動的代碼量將不可想象。另一方面,假如要換數據庫產品或者運行環境也可能是個不可能完成的任務。而用戶的運行環境和要求卻千差萬別,我們不可能為每一個用戶每一種運行環境設計一套一樣的系統。
所以就要將一樣的處理代碼即業務邏輯和可能不一樣的處理即數據存取邏輯分離開來,另一方面,關系型數據庫中的數據基本都是以一行行的數據進行存取的,而程序運行卻是一個個對象進行處理,而目前大部分數據庫驅動技術(如ADO.NET、JDBC、ODBC等等)均是以行集的結果集一條條進行處理的。所以為解決這一困難,就出現 ORM 這一個對象和數據之間映射技術。
舉例來說,比如要完成一個購物打折促銷的程序,用 ORM 思想將如下實現(引自《深入淺出Hibernate》):
業務邏輯如下:
public Double calcAmount(String customerid, double amount)
{
// 根據客戶ID獲得客戶記錄
Customer customer = CustomerManager.getCustomer(custmerid);
// 根據客戶等級獲得打折規則
Promotion promotion = PromotionManager.getPromotion(customer.getLevel());
// 累積客戶總消費額,并保存累計結果
customer.setSumAmount(customer.getSumAmount().add(amount);
CustomerManager.save(customer);
// 返回打折后的金額
return amount.multiply(protomtion.getRatio());
}
這樣代碼就非常清晰了,而且與數據存取邏輯完全分離。設計業務邏輯代碼的時候完全不需要考慮數據庫JDBC的那些千篇一律的操作,而將它交給 CustomerManager 和 PromotionManager 兩個類去完成。這就是一個簡單的 ORM 設計,實際的 ORM 實現框架比這個要復雜的多。
目前有哪些流行的 ORM 產品
目前眾多廠商和開源社區都提供了持久層框架的實現,常見的有
Apache OJB (http://db.apache.org/ojb/)
Cayenne (http://objectstyle.org/cayenne/)
Jaxor (http://jaxor.sourceforge.net)
Hibernate (http://www.hibernate.org)
iBatis (http://www.ibatis.com)
jRelationalFramework (http://ijf.sourceforge.net)
mirage (http://itor.cq2.org/en/oss/mirage/toon)
SMYLE (http://www.drjava.de/smyle)
TopLink (http://otn.oracle.com/products/ias/toplink/index.html)
其中 TopLink 是 Oracle 的商業產品,其他均為開源項目。
其中 Hibernate 的輕量級 ORM 模型逐步確立了在 Java ORM 架構中領導地位,甚至取代復雜而又繁瑣的 EJB 模型而成為事實上的 Java ORM 工業標準。而且其中的許多設計均被 J2EE 標準組織吸納而成為最新 EJB 3.0 規范的標準,這也是開源項目影響工業領域標準的有力見證。
參考文獻:1、《深入淺出Hibernate》
2、《精通Hibernate:Java對象持久化技術詳解》