Hibernate與Ibatis比較

hibernate和Ibatis比較java

hibernate 是當前最流行的o/r mapping框架,它出身於sf.net,如今已經成爲jboss的一部分了。
ibatis 是另一種優秀的o/r mapping框架,目前屬於apache的一個子項目了。 
相對hibernate「o/r」而言,ibatis是一種「sql mapping」的orm實現。 
hibernate對數據庫結構提供了較爲完整的封裝,hibernate的o/r mapping實現了pojo 和數據庫表之間的映射,以及sql 的自動生成和執行。程序員每每只需定義好了pojo 到數據庫表的映射關係,便可經過hibernate 提供的方法完成持久層操做。程序員甚至不須要對sql 的熟練掌握, hibernate/ojb 會根據制定的存儲邏輯,自動生成對應的sql 並調用jdbc 接口加以執行。 
而ibatis 的着力點,則在於pojo 與sql之間的映射關係。也就是說,ibatis並不會爲程序員在運行期自動生成sql 執行。具體的sql 須要程序員編寫,而後經過映射配置文件,將sql所需的參數,以及返回的結果字段映射到指定pojo。 
使用ibatis 提供的orm機制,對業務邏輯實現人員而言,面對的是純粹的java對象。
這一層與經過hibernate 實現orm 而言基本一致,而對於具體的數據操做,hibernate會自動生成sql 語句,而ibatis 則要求開發者編寫具體的sql 語句。相對hibernate而言,ibatis 以sql開發的工做量和數據庫移植性上的讓步,爲系統設計提供了更大的自由空間。 
hibernate與ibatis的對比:程序員

1.ibatis很是簡單易學,hibernate相對較複雜,門檻較高。 
2.兩者都是比較優秀的開源產品 
3.當系統屬於二次開發,沒法對數據庫結構作到控制和修改,那ibatis的靈活性將比hibernate更適合 
4.系統數據處理量巨大,性能要求極爲苛刻,這每每意味着咱們必須經過通過高度優化的sql語句(或存儲過程)才能達到系統性能設計指標。在這種狀況下ibatis會有更好的可控性和表現。 
5.ibatis須要手寫sql語句,也能夠生成一部分,hibernate則基本上能夠自動生成,偶爾會寫一些hql。一樣的需求,ibatis的工做量比hibernate要大不少。相似的,若是涉及到數據庫字段的修改,hibernate修改的地方不多,而ibatis要把那些sql mapping的地方一一修改。 
6.以數據庫字段一一對應映射獲得的po和hibernte這種對象化映射獲得的po是大相徑庭的,本質區別在於這種po是扁平化的,不像hibernate映射的po是能夠表達立體的對象繼承,聚合等等關係的,這將會直接影響到你的整個軟件系統的設計思路。 
7.hibernate如今已是主流o/r mapping框架,從文檔的豐富性,產品的完善性,版本的開發速度都要強於ibatis。sql

 

----ibatis原理淺析數據庫

 

對於iBATIS工做原理其實,若是使用iBATIS,iBATIS在後臺也是運行這些相同的JDBC代碼。iBATIS會獲取數據庫鏈接,設置SQL語句的參數,執行SQL語句,獲取執行結果,並在最後關閉全部的資源。然而,你須要本身親自編寫的代碼量卻大大地減小了。代碼清單2-3給出了使用iBATIS運行相同的SQL語句時你須要編寫的代碼。apache

2.1.iBATIS工做原理之於小型、簡單系統緩存

小型應用一般只涉及一個數據庫,只有一些至關簡單的用戶接口和領域模型。它的業務邏輯層很是簡單,有時對一些簡單的只涉及增查改刪(CRUD:Create, Read, Update, Delete)操做的應用來講甚至根本就不存在業務邏輯。iBATIS之因此很是適合於小型應用,有3個緣由。安全

第一,iBATIS本身就很小而且簡單。它不須要服務器或者其餘任何類型的中間件。不須要任何額外的基礎設施(infrastructure)。iBATIS也沒有任何第三方依賴。iBATIS的最簡安裝只須要2個JAR文件,總計不過375KB。除了須要配置一下你的SQL映射文件外,iBATIS不須要進行任何安裝,所以只須要幾分鐘時間你就能夠擁有一個可工做的持久層了。服務器

第二,iBATIS不會對現存應用的設計或者數據庫結構強加任何影響。所以,若是你有一個小型系統,且已經部分實現或者甚至已經發布了,則你仍然能夠重構你的持久層以使用iBATIS,這很是簡單。由於iBATIS很簡單,因此它根本不會使得應用的架構過度複雜。而若是使用對象/關係映射工具或者代碼生成工具,由於它們都事先就對應用以及數據庫的設計作了某些假設,所以它們不可能對應用的架構毫無影響。session

最後,只要你有過軟件開發的經驗,相信你就不會懷疑,任何一個小軟件都幾乎不可避免地有一天會成長爲一個大軟件。全部成功的軟件都有進一步成長的趨勢。這是一件好事,而咱們接下來想說的就是,iBATIS一樣很是適合於大型系統,它甚至能夠擴展以知足企業級應用的須要。架構

2.2 iBATIS工做原理之於大型、企業級系統

iBATIS就是爲企業級應用而設計的。最重要的是,iBATIS在這個領域比之其餘解決方案有着大量的優勢。iBATIS最初的建立者只有從大型應用到企業級應用系統的開發經驗。這一類系統一般都涉及不止一個數據庫,且全部這些數據庫都是不可控的。在第一章中咱們討論了各類類型的數據庫,包括企業級數據庫、私有數據庫和遺留數據庫。做者建立iBATIS框架一個很重要的緣由就是針對這樣的數據庫。所以,iBATIS擁有許多使其很是適合於企業應用環境的特色。

其實iBATIS適用於大型系統中的第一個緣由咱們已經說過了,不過這個緣由的確很重要,因此咱們仍是想再強調一下:iBATIS沒有對你的數據庫模型和對象模型的設計作任何假設。不論你的應用中這兩個模型之間是多麼不匹配,iBATIS都能適用。更進一步,iBATIS沒有對你的企業級應用的架構作出任何假設。不論你對數據庫是根據業務功能縱向劃分,仍是按照技術橫向劃分,iBATIS都容許你高效地處理數據並將它們整合到你的面向對象的應用中去。

第二點,iBATIS的某些特性使得它可以很是高效地處理大型數據集。iBATIS支持的行處理器(row handler)使得它可以批處理超大型記錄集,一次一條記錄。iBATIS也支持只獲取某個範圍內的結果,這就使得你能夠只獲取那些你當前亟需的數據。例如,假設你獲取了10,000條記錄,而你其實只須要其中的第500至600條,那你就能夠簡單的僅獲取這些記錄。iBATIS支持驅動提示使得執行這樣的操做很是高效。

最後一點,iBATIS容許你用多種方式創建從對象到數據庫的映射關係。一個企業級系統只以一種模式工做的狀況是很是少見的。許多企業級系統須要在白天執行事務性的工做,而在晚上執行批處理工做。iBATIS容許你將同一個類以多種方式映射,以保證每一種工做都能以最高效的方式執行。iBATIS一樣支持多種數據獲取策略。例如,你能夠選擇對某些數據進行懶加載,也能夠將一個複雜的對象圖只用一條聯合查詢SQL語句就同時加載完畢,從而避免嚴重的性能問題。

以上所說的這些彷佛好像在自我推銷了。那麼,既然咱們已經進入了這種狀態,爲什麼不繼續深刻研究一下你須要使用iBATIS的理由呢?咱們會在2.3節作這件事情。而且爲了公平起見,在2.4節中,咱們還會討論一些你不該該使用iBATIS的狀況。

 --------hibernate緩存(轉自:http://blog.csdn.net/woshichenxu/article/details/586361

 

1.     關於hibernate緩存的問題:

1.1.1.         基本的緩存原理

Hibernate緩存分爲二級,第一級存放於session中稱爲一級緩存,默認帶有且不能卸載。

 

第二級是由sessionFactory控制的進程級緩存。是全局共享的緩存,凡是會調用二級緩存的查詢方法都會從中受益。只有經正確的配置後二級緩存纔會發揮做用。同時在進行條件查詢時必須使用相應的方法才能從緩存中獲取數據。好比Query.iterate()方法、load、get方法等。必須注意的是session.find方法永遠是從數據庫中獲取數據,不會從二級緩存中獲取數據,即使其中有其所須要的數據也是如此。

 

查詢時使用緩存的實現過程爲:首先查詢一級緩存中是否具備須要的數據,若是沒有,查詢二級緩存,若是二級緩存中也沒有,此時再執行查詢數據庫的工做。要注意的是:此3種方式的查詢速度是依次下降的。

     由於Session的生命期每每很短,存在於Session內部的第一級最快緩存的生命期固然也很短,因此第一級緩存的命中率是很低的。其對系統性能的改善也是頗有限的。固然,這個Session內部緩存的主要做用是保持Session內部數據狀態同步。並不是是hibernate爲了大幅提升系統性能所提供的。

爲了提升使用hibernate的性能,除了常規的一些須要注意的方法好比:

使用延遲加載、迫切外鏈接、查詢過濾等之外,還須要配置hibernate的二級緩存。其對系統總體性能的改善每每具備立竿見影的效果!

(通過本身之前做項目的經驗,通常會有3~4倍的性能提升)

 

1.2.2.      N+1次查詢的問題

執行條件查詢時,iterate()方法具備著名的「n+1」次查詢的問題,也就是說在第一次查詢時iterate方法會執行知足條件的查詢結果數再加一次(n+1)的查詢。可是此問題只存在於第一次查詢時,在後面執行相同查詢時性能會獲得極大的改善。此方法適合於查詢數據量較大的業務數據。

可是注意:當數據量特別大時(好比流水線數據等)須要針對此持久化對象配置其具體的緩存策略,好比設置其存在於緩存中的最大記錄數、緩存存在的時間等參數,以免系統將大量的數據同時裝載入內存中引發內存資源的迅速耗盡,反而下降系統的性能!!!

 

1.3.   使用hibernate二級緩存的其餘注意事項:

1.3.1.      關於數據的有效性

另外,hibernate會自行維護二級緩存中的數據,以保證緩存中的數據和數據庫中的真實數據的一致性!不管什麼時候,當你調用save()、update()或 saveOrUpdate()方法傳遞一個對象時,或使用load()、 get()、list()、iterate() 或scroll()方法得到一個對象時, 該對象都將被加入到Session的內部緩存中。 當隨後flush()方法被調用時,對象的狀態會和數據庫取得同步。

 

也就是說刪除、更新、增長數據的時候,同時更新緩存。固然這也包括二級緩存!

 

只要是調用hibernate API執行數據庫相關的工做。hibernate都會爲你自動保證緩存數據的有效性!!

 

可是,若是你使用了JDBC繞過hibernate直接執行對數據庫的操做。此時,Hibernate不會/也不可能自行感知到數據庫被進行的變化改動,也就不能再保證緩存中數據的有效性!!

 

這也是全部的ORM產品共同具備的問題。幸運的是,Hibernate爲咱們暴露了Cache的清除方法,這給咱們提供了一個手動保證數據有效性的機會!!

一級緩存,二級緩存都有相應的清除方法。

 

其中二級緩存提供的清除方法爲:

按對象class清空緩存

                按對象class和對象的主鍵id清空緩存

                清空對象的集合中的緩存數據等。

   

1.3.2.      適合使用的狀況

並不是全部的狀況都適合於使用二級緩存,須要根據具體狀況來決定。同時能夠針對某一個持久化對象配置其具體的緩存策略。

 

適合於使用二級緩存的狀況:

一、數據不會被第三方修改;

 

通常狀況下,會被hibernate之外修改的數據最好不要配置二級緩存,以避免引發不一致的數據。可是若是此數據由於性能的緣由須要被緩存,同時又有可能被第3方好比SQL修改,也能夠爲其配置二級緩存。只是此時須要在sql執行修改後手動調用cache的清除方法。以保證數據的一致性

 

  二、數據大小在可接收範圍以內;

 

     若是數據表數據量特別巨大,此時不適合於二級緩存。緣由是緩存的數據量過大可能會引發內存資源緊張,反而下降性能。

 

若是數據表數據量特別巨大,可是常用的每每只是較新的那部分數據。此時,也可爲其配置二級緩存。可是必須單獨配置其持久化類的緩存策略,好比最大緩存數、緩存過時時間等,將這些參數下降至一個合理的範圍(過高會引發內存資源緊張,過低了緩存的意義不大)。

 

  三、數據更新頻率低;

 

     對於數據更新頻率太高的數據,頻繁同步緩存中數據的代價可能和查詢緩存中的數據從中得到的好處至關,壞處益處相抵消。此時緩存的意義也不大。

 

 

  四、非關鍵數據(不是財務數據等)

 

  財務數據等是很是重要的數據,絕對不容許出現或使用無效的數據,因此此時爲了安全起見最好不要使用二級緩存。

  由於此時「正確性」的重要性遠遠大於「高性能」的重要性。

2.     目前系統中使用hibernate緩存的建議

1.4.   目前狀況

 通常系統中有三種狀況會繞開hibernate執行數據庫操做:

一、多個應用系統同時訪問一個數據庫

   此種狀況使用hibernate二級緩存會不可避免的形成數據不一致的問題,

   此時要進行詳細的設計。好比在設計上避免對同一數據表的同時的寫入操做,

   使用數據庫各類級別的鎖定機制等。

 

二、動態表相關

   所謂「動態表」是指在系統運行時根據用戶的操做系統自動創建的數據表。

   好比「自定義表單」等屬於用戶自定義擴展開發性質的功能模塊,由於此時數據表是運行時創建的,因此不能進行hibernate的映射。所以對它的操做只能是繞開hibernate的直接數據庫JDBC操做。

      若是此時動態表中的數據沒有設計緩存,就不存在數據不一致的問題。

   若是此時自行設計了緩存機制,則調用本身的緩存同步方法便可。

 

三、使用sql對hibernate持久化對象表進行批量刪除時

     此時執行批量刪除後,緩存中會存在已被刪除的數據。

分析: 

   當執行了第3條(sql批量刪除)後,後續的查詢只多是如下三種方式:

a. session.find()方法:

根據前面的總結,find方法不會查詢二級緩存的數據,而是直接查詢數據庫。

因此不存在數據有效性的問題。

b. 調用iterate方法執行條件查詢時:

根據iterate查詢方法的執行方式,其每次都會到數據庫中查詢知足條件的id值,而後再根據此id 到緩存中獲取數據,當緩存中沒有此id的數據纔會執行數據庫查詢;

若是此記錄已被sql直接刪除,則iterate在執行id查詢時不會將此id查詢出來。因此,即使緩存中有此條記錄也不會被客戶得到,也就不存在不一致的狀況。(此狀況通過測試驗證)

 

c. 用get或load方法按id執行查詢:

 

客觀上此時會查詢獲得已過時的數據。可是又由於系統中執行sql批量刪除通常是

針對中間關聯數據表,對於

中間關聯表的查詢通常都是採用條件查詢 ,按id來查詢某一條關聯關係的概率很低,因此此問題也不存在!

 

   若是某個值對象確實須要按id查詢一條關聯關係,同時又由於數據量大使用了sql執行批量刪除。當知足此兩個條件時,爲了保證按id 的查詢獲得正確的結果,可使用手動清楚二級緩存中此對象的數據的方法!!

(此種狀況出現的可能性較小)

 

1.5.   建議

一、建議不要使用sql直接執行數據持久化對象的數據的更新,可是能夠執行批量刪除。(系統中須要批量更新的地方也較少)

 

二、若是必須使用sql執行數據的更新,必須清空此對象的緩存數據。調用

SessionFactory.evict(class)

SessionFactory.evict(class,id)

等方法。

 

三、在批量刪除數據量不大的時候能夠直接採用hibernate的批量刪除,這樣就不存在繞開hibernate執行sql產生的緩存數據一致性的問題。

 

四、不推薦採用hibernate的批量刪除方法來刪除大批量的記錄數據。

緣由是hibernate的批量刪除會執行1條查詢語句外加知足條件的n條刪除語句。而不是一次執行一條條件刪除語句!!

當待刪除的數據不少時會有很大的性能瓶頸!!!若是批量刪除數據量較大,好比超過50條,能夠採用JDBC直接刪除。這樣做的好處是隻執行一條sql刪除語句,性能會有很大的改善。同時,緩存數據同步的問題,能夠採用 hibernate清除二級緩存中的相關數據的方法。

調用 SessionFactory.evict(class) ;SessionFactory.evict(class,id)等方法。

 

因此說,對於通常的應用系統開發而言(不涉及到集羣,分佈式數據同步問題等),由於只在中間關聯表執行批量刪除時調用了sql執行,同時中間關聯表通常是執行條件查詢不太可能執行按id查詢。因此,此時能夠直接執行sql刪除,甚至不須要調用緩存的清除方法。這樣作不會致使之後配置了二級緩存引發數據有效性的問題。

 

退一步說,即便之後真的調用了按id查詢中間表對象的方法,也能夠經過調用清除緩存的方法來解決。

 

四、具體的配置方法 

根據我瞭解的不少hibernate的使用者在調用其相應方法時都迷信的相信「hibernate會自行爲咱們處理性能的問題」,或者「hibernate會自動爲咱們的全部操做調用緩存」,實際的狀況是hibernate雖然爲咱們提供了很好的緩存機制和擴展緩存框架的支持,可是必須通過正確的調用其纔有可能發揮做用!!因此形成不少使用hibernate的系統的性能問題,實際上並非hibernate不行或者很差,而是由於使用者沒有正確的瞭解其使用方法形成的。相反,若是配置得當hibernate的性能表現會讓你有至關「驚喜的」發現。下面我講解具體的配置方法.

 ibernate提供了二級緩存的接口: 
net.sf.hibernate.cache.Provider, 
同時提供了一個默認的 實現net.sf.hibernate.cache.HashtableCacheProvider, 
也能夠配置 其餘的實現 好比ehcache,jbosscache等。

具體的配置位置位於hibernate.cfg.xml文件中 
<property name="hibernate.cache.use_query_cache">true</property> 
<property name="hibernate.cache.provider_class">net.sf.hibernate.cache.HashtableCacheProvider</property>

不少的hibernate使用者在 配置到 這一步 就覺得 完事了, 
注意:其實光這樣配,根本 就沒有使用hibernate的二級緩存。同時由於他們在使用hibernate時大多時候是立刻關閉session,因此,一級緩存也沒有起到任何做用。結果就是沒有使用任何緩存,全部的hibernate操做都是直接操做的數據庫!!性能能夠想見。

正確的辦法是除了以上的配置外還應該配置每個vo對象的具體緩存策略,在影射文件中配置。例如:

<hibernate-mapping> 
<class name="com.sobey.sbm.model.entitySystem.vo.DataTypeVO" table="dcm_datatype"> 
<cache usage="read-write"/> 
<id name="id" column="TYPEID" type="java.lang.Long"> 
<generator class="sequence"/> 
</id>

<property name="name" column="NAME" type="java.lang.String"/> 
<property name="dbType" column="DBTYPE" type="java.lang.String"/> 
</class> 
</hibernate-mapping>


關鍵就是這個<cache usage="read-write"/>,其有幾個選擇 
read-only,read-write,transactional,等 
而後在執行查詢時 注意了 ,若是是條件查詢,或者返回全部結果的查詢,此時session.find()方法 不會獲取緩存中的數據。只有調用query.iterate()方法時纔會調緩存的數據。

同時 get 和 load方法 是都會查詢緩存中的數據 .

對於不一樣的緩存框架具體的配置方法會有不一樣,可是大致是以上的配置

(另外,對於支持事務型,以及支持集羣的環境的配置我會爭取在後續的文章中中 發表出來)

 

3.     總結

總之是根據不一樣的業務狀況和項目狀況對hibernate進行有效的配置和正確的使用,揚長避短。不存在適合於任何狀況的一個「萬能」的方案。

以上結論及建議均創建在本身在對 Hibernate 2.1.2中的測試結果以及之前的項目經驗的基礎上。若有謬處,請打家提出指正:)!

 

再談談HibernateIbatis的區別,哪一個性能會更高一些

答: 1Hibernate偏向於對象的操做達到數據庫相關操做的目的;而ibatis更偏向於sql語句的優化。

2Hibernate的使用的查詢語句是本身的hql,而ibatis則是標準的sql語句。

3Hibernate相對複雜,不易學習;ibatis相似sql語句,簡單易學。

性能方面:

1、若是系統數據處理量巨大,性能要求極爲苛刻時,每每須要人工編寫高性能的sql語句或存錯過程,此時ibatis具備更好的可控性,所以性能優於Hibernate

2、一樣的需求下,因爲hibernate能夠自動生成hql語句,而ibatis須要手動寫sql語句,此時採用Hibernate的效率高於ibatis

相關文章
相關標籤/搜索