在本文中咱們介紹並比較兩種最流行的開源持久框架:iBATIS和Hibernate,咱們還會討論到Java Persistence API(JPA)。咱們介紹每種解決方案並討論其所規定的品質,以及在普遍的應用場景中其各自的長處和缺點。而後咱們會基於諸如性能、移植性、複雜性以及對數據模型改變的適應性等因素來比較iBATIS、Hibernate和JPA。程序員
若是你是一個剛起步的Java程序員,新接觸持久性概念的話,那麼就把閱讀此文看成是接受一次這一主題以及大部分流行的開源持久性解決方案的啓蒙。若是你對這三種解決方案都很熟悉,而且只想要一個簡單的比較的話,那麼你會在「比較持久化技術」一節中找到相應的內容。數據庫
持久性(persistence)是數據的一個屬性,其確保即便是在應用的生命週期以外數據也是可用的。對於像Java這樣的面嚮對象語言來講,持久性確保了即便是在建立對象的應用中止執行以後對象的狀態還是可訪問的。編程
存在多種實現持久性的方法。傳統的解決這一問題的方法是使用文件系統來把須要的信息存儲在平面文件(flat file)中。這一方法很難用來管理大量的數據,由於數據分佈在不一樣的文件中。使用平面文件系統的話維護數據的一致性也是一個問題,由於相同的信息可能會被重複放在各個文件中。在平面文件中查找數據很耗時,特別是若是這些文件還未排序的話。還有,文件系統對併發訪問的支持有限,由於它們不能確保數據的完整性。基於上述種種緣由,在尋求持久性時,文件系統並不被視爲一個良好的數據存儲解決方案。緩存
當前最多見的方法是使用數據庫,其充當巨大量數據的存儲庫。存在許多種類型的數據庫:關係型的、層次結構型的、網絡型的、面向對象型的等等。這些數據庫,以及它們的數據庫管理系統(DBMS),不只提供持久性能力,並且管理其所持久的信息。關係數據庫是最被普遍使用的類型,關係數據庫中的數據被建模成一組相互關聯的表。網絡
企業級應用的出現普及了n層架構,其目的是經過把表現、業務和數據庫相關代碼分離到應用的不一樣層級(或是層面)中來提高可維護性。分離了業務邏輯和數據庫代碼的層面便是持久層,其保持了應用相對於底層的數據庫技術的獨立性。適當的位置上有了這一強健的層面,開發者就再也不須要操心數據的持久性。持久層封裝了存儲和檢索關係型數據庫中的數據的方式。架構
Java應用傳統上使用JDBC(Java Database Connectivity)API來把數據持久到關係數據庫中。JDBC API使用SQL語句來完成建立(create)、讀取(read)、更新(update)和刪除(delete)(CRUD)操做。JDBC代碼內嵌在Java類中——換句話說,這類代碼與業務邏輯緊密耦合在一塊兒。這類代碼還在很大程度上依賴於SQL,而SQL並不是是跨數據庫的標準;這使得從一種數據庫移植到另外一種數據庫變得困難起來。併發
關係數據庫技術強調的是數據及其之間的關係,而用於Java中的面向對象範式卻並不是關注數據自己,而是關注執行於數據之上的操做。所以,當這兩種技術須要攜手合做時,就會存在利益衝突。並且,關係數據庫並不能知足繼承、多態及關聯這些面向對象編程概念。當Java應用中的用戶定義的數據類型被映射到關係數據庫上時,由這一失配致使的另外一個問題就出現了,由於後者並無提供所需的類型支持。app
對象關係映射(object-relational mapping,ORM)已成爲了有時被稱做對象關係阻抗失配(impedance mismatch)的這一問題的一個解決方案。ORM是一種透明地把應用對象持久到關係數據庫中的表的技術。ORM的行爲就像是一個虛擬的數據庫,對用戶隱藏了底層的數據庫架構。ORM提供功能來執行完整的CRUD操做並鼓勵面向對象的查詢。ORM還支持元數據映射以及在應用的事務管理方面提供幫助。框架
舉個例子有助於說明ORM是如何工做的。考慮一個須要持久到數據庫中的簡單的Car對象,領域模型中的這一Car對象是數據模型中的CAR表的表現形式。Car對象的屬性派生自CAR表的各列。在Car類和CAR表之間存在一個直接映射。數據庫設計
存在許多開源的ORM工具,其中包括Hibernate、iBATIS SQL Maps以及Java Ultra-Lite Persistence等。這些工具大多數是提供Java應用和數據庫之間的抽象層的持久性框架。持久性框架把應用領域中的對象映射成須要持久在數據庫中的數據,這些映射可以使用XML文件或是元數據註解(後者做爲Java1.5的組成部分被引入到語言中)來定義。持久性框架的目的是分離數據庫相關代碼和應用代碼(即業務邏輯),從而提升應用的靈活性。持久性框架經過提供一個持久性邏輯的包裝器來簡化開發過程。
完成了持久性的基本介紹以後,咱們就作好了繼續討論兩種最流行的開源持久框架iBATIS和Hibernate的準備。咱們還會介紹Java Persistence API,並討論這三種解決方案在各類應用場景中的優點和弱點。
iBATIS最好是用在你須要全面地控制SQL的時候,在須要對SQL查詢作微調的時候也頗有用。當你在應用和數據庫設計兩方面都有徹底的控制權的時候,就不該該使用iBATIS,由於在這樣的狀況下,應用可能會作出修改以適應數據庫,或是反過來。在這種情形中,你能夠構建一個徹底的對象-關係應用,其餘的ORM工具更適於使用,由於iBATIS較爲以SQL爲中心,其一般被稱做反轉的——功能齊全的ORM工具生成SQL,而iBATIS直接使用SQL。iBATIS也不適合於非關係型的數據庫,由於這類數據庫不支持事務和其餘iBATIS用到的鍵特性。
Hibernate最適合用來做爲端到端的OR映射的手段。其提供了一個完整的ORM解決方案,但可是不會讓你控制查詢。對於那些對應用和數據庫二者都有徹底的控制權的狀況來講,Hibernate是一種理想的解決方案。在這類狀況中,你能夠修改應用來適用數據庫,反之亦然,在這些狀況下你可使用Hibernate來構建一個全對象-關係應用。對於不太熟悉SQL的面向對象編程者來講,Hibernate是最佳選擇。
JPA應該用在須要標準的基於Java的持久性解決方案的時候。JPA支持繼承和多態這兩種面向對象編程特性。JPA的缺點是其須要一個實現了其自身的提供程序。這些供應商特有的工具還提供了某些並未定義成JPA規範組成部分的特性,其中一個這樣的特性是緩存支持,該功能並未在JPA中作明肯定義,但其中一個最流行的實現了JPA的框架Hibernate對這一功能提供了很好的支持。
此外,JPA被定義成只能在關係數據庫上工做。若是你的持久化解決方案須要擴展到其餘類型的數據存儲上,好比XML數據庫上的話,則JPA就不可以用來解決你的持久性問題了。
比較持久化技術
如今你已經分析了三種不一樣的持久化機制及其運做方式。這些框架中的每一種都有本身的優勢和缺點。讓咱們來考慮幾個參數,這些參數可幫助你肯定其中知足你需求的最佳可行方案。
簡易性
在許多應用的開發中,時間是主要的制約因素,特別是當團隊成員須要經培訓來使用某種特定框架的時候。在這類情形中,iBATIS是最好的選擇,該框架是三種框架中最簡單的,由於它僅需SQL方面的知識就夠了。
完整的ORM解決方案
像Hibernate和JPA一類的傳統的ORM解決方案應該用來做爲一種徹底的對象-關係映射手段。Hibernate和JPA直接把Java對象映射到數據庫表上,而iBATIS則是把Java對象映射到SQL查詢的結果上。在某些應用中,領域模型中的對象是根據業務邏輯來設計的,可能不徹底與數據模型匹配,在這種狀況下,iBATIS是合適的選擇。
對SQL的依賴
老是會存在精通Java的人和更信任SQL的人這樣的一種劃分,對於一個熟練的Java程序員來講,他想使用一個無需與SQL有太多交互的持久性框架,那麼Hibernate是最好的選擇,由於它會在運行時生成高效率的SQL查詢。可是,若是你想要使用存儲過程來對數據庫查詢作各方面的控制的話,則iBATIS是推薦的解決方案。JPA還可經過EntityManager的createNativeQuery()方法來支持SQL。
支持的查詢語言
iBATIS大力支持SQL,而Hibernate和JPA則是使用它們本身的查詢語言(分別是HQL和JPQL),這些語言與SQL相似。
性能
一個應用要成功的話須要具有良好的性能。Hibernate經過提供緩存設施來提升性能,這些緩存設施有助於更快地從數據庫中檢索數據。iBATIS使用SQL查詢,這些查詢可經過微調來得到更佳性能。JPA的性能則取決於供應商的實現,根據每一個應用的特有狀況作選擇。
跨不一樣數據庫的移植性
有時候,你須要改變應用使用的關係數據庫,若是你使用Hibernate來做爲持久化解決方案的話,那麼這一問題很容易解決,由於Hibernate在配置文件中使用了一個數據庫方言屬性。從一個數據庫移植到另外一個數據庫上僅是把dialect屬性修改爲適當值的事。Hibernate使用這一屬性來做爲生成特定於某種給定數據庫的SQL代碼的指南。
如前所述,iBATIS要求你編寫本身的SQL代碼,所以,iBATIS應用的可移植性取決於這些SQL。若是查詢是使用可移植的SQL編寫的話,那麼iBATIS也是可在不一樣的關係數據庫之間作移植的。另外一方面,JPA的移植性則取決於其正在使用的供應商實現。JPA是可在不一樣的實現之間作移植的,好比Hibernate和TopLink Essentials之間。所以,若是應用沒有用到某些提供商特有的功能特性的話,那麼移植性就不是什麼大問題。
社區支持和文檔
在這方面,Hibernate明顯是個贏家。存在許多以Hibernate爲焦點的論壇,在這些論壇中社區成員都會積極地回答各類問題。關於這一點,iBATIS和JPA正慢慢遇上。
跨非Java平臺的移植性
iBATIS支持.Net和Ruby on Rails。Hibernate以NHibernate的形式爲.Net提供了一個持久性解決方案。JPA,做爲特定於Java的API,顯然並不支持任何的非Java平臺。
表1給出了這一比較的一個總結。
表1. 持久性解決方案比較
特性 |
iBATIS |
Hibernate |
JPA |
簡易性 |
優 |
良 |
良 |
完整的ORM解決方案 |
通常 |
優 |
優 |
對數據模型改變的適應性 |
良 |
通常 |
通常 |
複雜性 |
優 |
通常 |
通常 |
對SQL的依賴 |
良 |
通常 |
通常 |
性能 |
優 |
優 |
不適用* |
跨不一樣關係數據庫的移植性 |
通常 |
優 |
不適用* |
非Java平臺的移植性 |
優 |
良 |
不支持 |
社區支持和文檔 |
通常 |
良 |
良 |
*JPA對這些特性的支持取決於持久性提供程序,最終的結果可能會視狀況各異。
結論
iBATIS、Hibernate和JPA是用於把數據持久到關係數據庫中的三種不一樣的機制,每種都有着本身的優點和侷限性。iBATIS不提供完整的ORM解決方案,也不提供任何的對象和關係模型的直接映射。不過,iBATIS給你提供了對查詢的全面控制權。Hibernate提供了一個完整的ORM解決方案,但不提供對查詢的控制權。Hibernate很是的受歡迎,有一個龐大而活躍的社區爲新用戶提供支持。JPA也提供一個完整的ORM解決方案,並提供對諸如繼承和多態一類的面向對象編程特性的支持,不過它的性能則取決於持久性提供程序。
某個特定持久性機制的選擇事關全部功能特性的權衡,這些特性在本文的比較章節中都作了討論。對於大部分的開發者來講,須要根據是否要求對應用的SQL作全面控制、是否須要自動生成SQL,或僅是想要一個易於編程的完整的ORM解決方案等各方面的考慮來作決定。