為什麼阿里巴巴的持久層採用iBatis框架,而不使用hibernate框架呢?感覺hibernate更厲害的樣子?

如題...


你試過調優hibernate嗎?試過之後你就不會問這個問題了。

hibernate的適用場景是你不知道你的產品要部署到什麼資料庫,弄一個大而重的ORM層可以免去根據不同資料庫寫不同SQL的問題。而對阿里而言,使用的是自己定製的mysql或者自己的oceanBase,不存在這種問題。


先說hibernate厲害在哪,然後再來說為啥享受hibernate這些便利會有問題。

hibernate讓你可以不寫sql,這不單可以讓你的應用更好移植到其他資料庫,更主要是讓程序員可以更專註與業務邏輯,更關注於數據和數據、對象和對象之間的關係。hibernate對一對多,多對多關係實現的是非常好的。很關鍵的一點,它支持lazy,可以讓你的數據只在需要的時候被load,聽起來非常美是不是?hibernate還有一個很牛的feature就是可以用HQL,這是完全可以把查詢映射到你OO模型的查詢語言,和ibatis等的映射比起來,還是要方便和感覺強大一些的。

如果這麼看,似乎沒有不用hibernate的道理,但其實不是的,我牆裂建議不用hibernate,尤其是需要處理大量數據或者大並發情況的網站服務,那麼現在開始說hibernate的問題。

首先,hibernate把資料庫和你隔離了,你不需要關注資料庫是mysql還是oracle,hibernate來幫你生成查詢的sql。但問題也來了,如果你就要用某種資料庫特有的功能,或者你就要讓查詢的sql完全符合你的心意,這就難了。而據我所知,阿里是在mysql上下了大功夫的,而且他們對數據查詢的要求也比較高,很多sql查詢都要精心設計,如果使用hibernate,雖然它也能對生成的查詢進行一定程度的定製,但就有點隔靴搔癢了,而且你開發起來付出的代價可能更大。至於hibernate對native sql的支持,就像評論中有朋友提到的,其實也還是完善的,有興趣的朋友可以看看。而且這種native sql還能返回non-managed entity,不走hibernate的cache,優化是能搞了,但如果你整個項目都這麼搞,那還是ibatis對sql管理的好些。

第二,對於阿里這種scale的網站服務,對cache的依賴是非常大的,hibernate自帶的cache按理說也是很強大的,但是還是不能滿足像阿里這樣的公司的需求。一般來說,阿里這樣的網站對cache邏輯的要求是非常高的,而且一定要具體問題,具體優化。那麼hibernate的那一套cache就顯得多餘,甚至可能有副作用了。

第三,hibernate的確是在你項目開始的時候給你節約了很多時間。但是它讓你的業務邏輯模型和資料庫模型互相依賴的程度太高了。這短期沒有問題,但隨著項目的變遷,這些都會改變,在維持這種緊緊耦合的關係的時候,你會發現你的代碼特別脆弱,隨便改一處資料庫的schema,整個java項目可能要改幾十處。而且現在mybatis的自動mapping做的也不差,開發起來也沒多花多少時間。等項目進入中後期,你需要大量定製和優化查詢的時候,mybatis的開發效率就勝出了。

還有一點可能是我個人喜好了,作為一個後端程序員,我比較喜歡每一行代碼我都精確知道它到底在幹什麼。尤其是資料庫訪問的代碼,往往系統的瓶頸就在這些地方產生,每一行都不能小看。我看過hibernate早期版本的部分代碼,比我想像的複雜和強大很多。的確很多地方Hibernate可以強大的只用一行代碼解決很多問題,但比如說一個update()或者save()到底做了什麼,這裡既有hibernate本身的邏輯,也有你應用的邏輯,如果這一行產生了問題,你該如何去做?我個人覺得這是很難搞的,還不如一開始費點事,用ibatis這種。

其實還有不少問題,我有時間再回來寫。


Mybatis最大好處是在靈活度和方便性方面取得平衡,雖然「手工活兒」會多一些,但是你可以在需要的時候通過SQL換取靈活度和性能。

一個大而全的ORM固然讓人更便捷和更「賞心悅目」,但也變得笨重,在一般性系統中,這可能不是問題,但在大型系統上可能就滿足不了性能或擴充性的需求。

從這點上發散開來看,軟體開發模式並不是「形而上」,有時候「反模式」可能更有效。教科書和理論是一回事兒,但軟體成效最終要靠實踐來體現,只有實效性才有說服力。


兩個框架各有千秋,ibatis暴露sql,sql都需要自己寫,hibernate有自己的hql封裝以及強大的模型映射。 對於阿里來說,很多sql並不複雜,而且不能複雜,核心鏈路上我們超過100ms的就算慢sql了。所以ibatis開發和調優更加方便簡單


)iBATIS非常簡單易學,Hibernate相對較複雜,門檻較高。iBATIS拿來文檔看半天到兩天就可以掌握了。Hibernate可能需要3倍以上的時間來掌握。

2) 二者都是比較優秀的開源產品。但Hibernate現在已經是主流O/R Mapping框架,從文檔的豐富性,產品的完善性,版本的開發速度都要強於iBATIS。

3) 當系統屬於二次開發,無法對資料庫結構做到控制和修改,那iBATIS的靈活性將比Hibernate更適合。

4) 系統數據處理量巨大,性能要求極為苛刻,這往往意味著我們必須通過經過高度優化的SQL語句(或存儲過程)才能達到系統性能設計指標。在這種情況下iBATIS會有更好的可控性和表現。iBatis比Hibernate更容易進行sql的優化。鑒於一般系統性能的瓶頸都在資料庫上,所以這一點是iBatis非常重要的一個優勢。

5) iBatis 可以進行細粒度的優化

  • 比如說我有一個表,這個表有幾個或者幾十個欄位,我需要更新其中的一個欄位,iBatis很簡單,執行一個sql:UPDATE TABLE_A SET column_1=#column_1# WHERE id=#id# 但是用Hibernate的話就比較麻煩了,預設的情況下hibernate會更新所有欄位。當然,hibernate有一個選項可以控制只保存修改過的欄位。
  • 我需要列出一個表的部分內容,用iBatis的時候,這裡面的好處是可以少從資料庫讀很多數據,節省流量SELECT ID, NAME FROM TABLE_WITH_A_LOT_OF_COLUMN WHERE ...
    • 一般情況下Hibernate會把所有的欄位都選出來。比如說有一個上面表有8個欄位,其中有一兩個比較大的欄位,varchar(255)/text。上面的場景中我為什麼要把他們也選出來呢?
    • 用hibernate的話,你又不能把這兩個不需要的欄位設置為lazy load,因為還有很多地方需要一次把整個 domain object 載入出來。這個時候就能顯出ibatis的好處了。
    • Hibernate還有一個方案,就是生成javabean/map/object[](感謝leelun/cjmm),但是這樣的話就可能會產生大量的多餘class。map/object[] 的方式應該不錯,我比較喜歡這種方式。
  • 如果我需要更新一條記錄(一個對象),如果使用hibernate,需要現把對象select出來,然後再做update。這對資料庫來說就是兩條 sql。而iBatis只需要一條update的sql就可以了。減少一次與資料庫的交互,對於性能的提升是非常重要。

6) iBatis需要手寫sql語句,也可以生成一部分,Hibernate則基本上可以自動生成,偶爾會寫一些Hql。同樣的需求,iBATIS的工作量比Hibernate要大很多。類似的,如果涉及到資料庫欄位的修改,Hibernate修改的地方很少,而iBATIS要把那些sql mapping的地方一一修改。

7) 開發方面

  • 開發效率上,我覺得兩者應該差不多
  • 可維護性方面,我覺得iBatis更好一些。因為iBatis的sql都保存到單獨的文件中。而Hibernate在有些情況下可能會在java代碼中保存sql/hql。

8) 運行效率

在不考慮cache的情況下,iBatis應該會比hibernate快一些或者很多(根據實際情況會有所不同)。

9) 對不同資料庫類型的支持。iBatis對不同資料庫類型的支持不夠好,如果你要開發的系統是要在對中數據間移植,那可能用hibernate比較好。

10)對預設的cache支持。iBatis對預設的cache支持不夠好,但是hibernate的cache支持其實也不是很好,而且很複雜。尤其是對於大並發量的應用。所以我更傾向於自己管理cache。

11) 以資料庫欄位一一對應映射得到的PO(persistant object)和Hibernte這種對象化映射得到的PO是截然不同的,本質區別在於這種PO是扁平化的,不像Hibernate映射的PO是可以表達立體的對象繼承,聚合等等關係的,這將會直接影響到你的整個軟體系統的設計思路。

12) 最關鍵的一句話是iBATIS的作者說的:If you are starting a new project and you"re in full control of your object model and database design, Hibernate is a good choice of O/R tool.If you are accessing any 3rd party databases (e.g. vendor supplied), or you"re working with a legacy database, or even just a really poorly designed database, then an O/R mapper might not be capable of handling the situation. That"s were an SQL Mapper comes in handy


瀉藥

感覺hibernate更厲害啊,嗯,hibernate其實就是jee裡面jpa的原型

你是不是也感覺jee很厲害呢?

很可惜,互聯網時代,這些東西都有些慢

資料庫本來就慢,加上orm,哎呀呀呀,好慢好慢呀

用nosql最快


越大型的系統,越要側重確定性與可調性。

為此,犧牲一些易用性是值得的。

況且hibernate,一出翔你要不是專家還真不知道怎麼擦。

mybitas相比之下,雖然麻煩了一丟丟,但執行路徑和效果都是完全確定的。


ibatis不熟悉,沒有使用過。用的是MyBatis,

來一張圖說明一下MyBatis和hibernate 的區別吧。

hibernate相對於Mybatis而言是一個重量級框架,封裝sql語句,表映射,但是對於一些複雜的sql語句,hibernate暫時好像還達不到業務需求。hibernate更適合於傳統項目,而對於時下的互聯網行業,邏輯越來越複雜,所以很多SQL語句還是的自己寫。個人理解。

MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis。2013年11月遷移到Github。


適合是第一要務.


SQL的變化也屬於變更項,每一個變更都要做到可控可評估,使用iBatis更容易做到這一點,而且也方便讓DBA來優化。螞蟻內部用的dalgen代碼生成工具,可以根據xml配置自動生成DO,DAO,所以用起來也沒多少編碼量,很多都自動生成了。


因為比較有錢有人。

人不行,還硬用ibatis,以為自己手寫就是牛逼,就是把控的真好呀。結果玩崩了,寫出來的垃圾sql連ORM自動生成的都趕不上。

嗯,看場景,看人。


?寫查詢語句可以調優

?第三範式還要求你不要冗餘呢,但是阿里巴巴為啥三表禁止join?

?精於心簡於形

真正好用的東西不是代碼上的簡單,而是靠複雜的後台支撐簡潔快速的體驗!


Hibernate是OR-Mapping框架,與之相似的還有個Toplink(Oracle收購後開源了,用的人不多),而myBatis是SQL-Mapping框架,這兩者的設計出發點完全不同。

OR-Mapping框架認為開發者應該用面向對象的視角去建模(Domain),抽象業務實體(Object,嚴格意義上說是Entity),指定業務實體之間的關係(Relationship),並針對實體進行編程。按照這種邏輯,開發者只要說明實體之間的關係,持久化都由OR-Mapping框架來接管,理論上開發者甚至不用知道資料庫的存在,實際上Hibernate也確實可以自動生成各種實體和關係表以及相應的SQL語句。由於OR-Mapping如此傾向於OO Design,所以它和DDD(領域驅動開發)結合也很自然,用OR-Mapping配合DDD的domain會非常舒服,domain package中基本不會有額外的類存在,而且OR-Mapping給出的各種關係(1:1,1:N,N:M,lock,etc..)的最佳實踐,遵照這些標準資料庫Schema基本不會反範式。

在單庫單表的環境上如果開發者足夠熟練,用OR-Mapping可以優雅地搞定90%的需求,剩下的10%框架也提供自定義查詢甚至原生SQL支持的功能來實現,生成的SQL也足夠優秀(如果SQL不對,一定是建模有問題)。

但加黑的兩個前提往往不能滿足,這也是現在OR-Mapping往往不能適用的原因。

  1. 單庫單表。現在的互聯網應用為了scale out基本都會分庫分表,而OR-Mapping框架對sharding支持很差,比如hibernate sharding基本就沒啥人用。阿里使用myBatis當然有SQL review的原因,但即使現在大部分SQL已經不 review了,底層用分庫分表的TDDL直接就不適合用hibernate。
  2. 開發者學習成本。用好hibernate需要開發者對面向對象有比較清楚的了解,並且對hibernate內部機制和SQL比較熟悉,這樣遇到10%的問題時才能比較優雅地解決。學習曲線很陡峭,至少要一年才能優雅的幹活,在此前總會質疑「這個問題是不是沒法解」?非互聯網公司,能把hibernate用好的人也不多,從技術選型的角度,自然選的也比較少了。

SQL-Mapping就比較簡單了,就是對JDBC作簡單的封裝,入手極快,且可控性強。它也有缺點,比如在java代碼中多出一堆Mapper,PO,TO之類的東西,但瑕不掩玉,用的人自然越來越多。


寫hibernate 的hql之後,為了查問題,還需要把轉換之後的sql拿出來進行排查。

多少次,一個複雜的sql手寫幾分鐘,但是翻譯成hql後,總有小驚喜。更不要說在調sql的性能問題了。

還有ibatis這種,不需要考慮hibernate的緩存引入的問題…

普通人,熟練使用了sql,就能熟練使用ibatis/mybatis,而為了用好hibernate,你還需要認真去讀hibernate reference.


hibernate永遠會讓自認為精通hibernate的人懷疑人生


因為大多數情況下,我們並不需要整行信息


?怎麼跟網上宣傳的不一樣,不是自己專門寫的框架嗎,和優酷用的是同一框架


這主要涉及到兩個詞,一個叫效率,一個叫靈活度。

使用 hibernate 主要是利用了第一個詞 「效率」,沒錯,用 hibernate 可以快速實現一個項目,開始用起來感覺很爽,不用寫 sql ,全部用代碼實現。但是用著用著,當發現業務上一些個性化的需求越來越多,hibernate 的不便之處就顯現出來了,靈活度太低。本來寫一個 sql 就可以解決的問題,用 hibernate 實現起來確感覺很麻煩。

而 iBatis 則是幫我們做了一些繁瑣的工作,但同時保留了高度的靈活度,讓我們針對一些個性化需求可以定製 sql 語句,簡單來說就是高度可控。一切盡在我掌握之中,才能使我們廣大開發人員安心,不是么。


是啊,沒毛病,只是只要團隊有一個人用的不好,就雪崩


有時候更厲害的反而不太好。mybatis框架簡單直觀,方便調優。而hibernate更重一些。當然我還是更喜歡hibernate。

不過看起來厲害的東西並不一定就是好用的。舉個我自己的例子。以前我想用hibernate寫一個博客管理系統。由於hibernate有一個屬性映射功能。我可以在用戶類上增加一個文章列表欄位,等到需要顯示文章的時候,直接訪問這個欄位就可以查出用戶的所有文章了,是不是很屌的功能?酷不酷,想不想學?但是我用了結果一直蹦異常,查了大半天才發現原來事情是這樣的。默認情況下這個級聯欄位是懶載入的,只有當你查的時候hibernate採取執行查詢操作,但是因為我不是立刻使用這個欄位,所以有時候會拖到超出了spring管理的作用域外面,也就是真正需要查詢的時候spring以為我查完了,自動幫我把查詢實例關了。解決辦法一個是關掉懶載入,一次性全查完,這當然是不可能的;第二種就是不要用這種級聯欄位,老老實實一個類對應一張表,不要搞這些虛的。所以你看,看上去很厲害的,真正用起來可能會比較蛋疼


推薦閱讀:

本科國貿想讀計算機軟體與理論專業研究生?
未來你會選擇微軟的 Surface 平板電腦嗎?
想學習計算機圖像處理方面從哪入手,怎麼個學習順序,體系?
電腦中一個G的文件有多重?
計算機補碼運算背後的數學原理是什麼?

TAG:軟體開發 | 計算機 | Java | Hibernate | MyBatis |