數(shù)據(jù)持久化框架為什么放棄 Hibernate、JPA、Mybatis最終選擇 JDBCTemplate_第1頁
數(shù)據(jù)持久化框架為什么放棄 Hibernate、JPA、Mybatis最終選擇 JDBCTemplate_第2頁
數(shù)據(jù)持久化框架為什么放棄 Hibernate、JPA、Mybatis最終選擇 JDBCTemplate_第3頁
數(shù)據(jù)持久化框架為什么放棄 Hibernate、JPA、Mybatis最終選擇 JDBCTemplate_第4頁
數(shù)據(jù)持久化框架為什么放棄 Hibernate、JPA、Mybatis最終選擇 JDBCTemplate_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

數(shù)據(jù)持久化框架為什么放棄Hibernate、JPA、Mybatis,最終選擇JDBCTemplate!一、SQL封裝和性能二、DSL和變化適應性三、跨數(shù)據(jù)庫移植四、安全性五、JOOQ的失敗之處因為項目需要選擇數(shù)據(jù)持久化框架,看了一下主要幾個流行的和不流行的框架,對于復雜業(yè)務系統(tǒng),最終的結(jié)論是,JOOQ是總體上最好的,可惜不是完全免費,最終選擇JDBCTemplate。Hibernate和Mybatis是使用最多的兩個主流框架,而JOOQ、Ebean等小眾框架則知道的人不多,但也有很多獨特的優(yōu)點;而JPA則是一組Java持久層Api的規(guī)范,SpringDataJPA是JPARepository的實現(xiàn),本來和Hibernate、Mybatis、JOOQ之類的框架不在同一個層次上,但引入SpringDataJPA之類框架之后,我們會直接使用JPA的API查詢更新數(shù)據(jù)庫,就像我們使用Mybatis一樣,所以這里也把JPA和其他框架放在一起進行比較。同樣,JDBC和其他框架也在同一層次,位于所有持久框架的底層,但我們有時候也會直接在項目中使用JDBC,而SpringJDBCTemplate部分消除了使用JDBC的繁瑣細節(jié),降低了使用成本,使得我們更加愿意在項目中直接使用JDBC。一、SQL封裝和性能在使用Hibernate的時候,我們查詢的是POJO實體類,而不再是數(shù)據(jù)庫的表,例如hql語句selectcount(*)fromUser,里面的User是一個Java類,而不是數(shù)據(jù)庫表User。這符合ORM最初的理想,ORM認為Java程序員使用OO的思維方式,和關(guān)系數(shù)據(jù)庫的思維方式差距巨大,為了填補對象和關(guān)系思維方式的鴻溝,必須做一個對象到關(guān)系的映射,然后在Java的對象世界中,程序員可以使用純的對象的思維方式,查詢POJO對象,查詢條件是對象屬性,不再需要有任何表、字段等關(guān)系的概念,這樣java程序員就更容易做持久層的操作。JPA可以視為Hibernate的兒子,也繼承了這個思路,把SQL徹底封裝起來,讓Java程序員看不到關(guān)系的概念,用純的面向?qū)ο笏枷?,重新?chuàng)造一個新的查詢語言代替sql,比如hql,還有JPQL等。支持JPA的框架,例如Ebean都屬于這種類型的框架。但封裝SQL,使用另一種純的面向?qū)ο蟛樵冋Z言代替sql,真的能夠讓程序員更容易實現(xiàn)持久層操作嗎?MyBatis的流行證明了事實并非如此,至少在大多數(shù)情況下,使用hql并不比使用sql簡單。首先,從很多角度上看,hql/JPQL等語言更加復雜和難以理解;其次就是性能上明顯降低,速度更慢,內(nèi)存占用巨大,而且還不好優(yōu)化。最為惱火的是,當關(guān)系的概念被替換為對象的概念之后,查詢語言的靈活性變得很差,表達能力也比sql弱很多。寫查詢語句的時候受到各種各樣的限制,一個典型的例子就是多表關(guān)聯(lián)查詢。不管是hibernate還是jpa,表之間的連接查詢,被映射為實體類之間的關(guān)聯(lián)關(guān)系,這樣,如果兩個實體類之間沒有(實現(xiàn))關(guān)聯(lián)關(guān)系,你就不能把兩個實體(或者表)join起來查詢。這是很惱火的事情,因為我們很多時候并不需要顯式定義兩個實體類之間的關(guān)聯(lián)關(guān)系就可以實現(xiàn)業(yè)務邏輯,如果使用hql,只是為了join我們就必須在兩個實體類之間添加代碼,而且還不能逆向工程,如果表里面沒有定義外鍵約束的話,逆向工程會把我們添加的關(guān)聯(lián)代碼抹掉。MyBatis則是另外一種類型的持久化框架,它沒有封裝SQL也沒有創(chuàng)建一種新的面相對象的查詢語言,而是直接使用SQL作為查詢語言,只是把結(jié)果填入POJO對象而已。使用sql并不比hql和JPQL困難,查詢速度快,可以靈活使用任意復雜的查詢只要數(shù)據(jù)庫支持。從SQL封裝角度上看,MyBatis比Hibernate和JPA成功,SQL本不該被封裝和隱藏,讓Java程序員使用SQL既不麻煩也更容易學習和上手,這應該是MyBatis流行起來的重要原因。輕量級持久層框架JOOQ也和MyBatis一樣,直接使用SQL作為查詢語言,比起MyBatis,JOOQ雖然知名度要低得多,但JOOQ不但和MyBatis一樣可以利用SQL的靈活性和高效率,通過逆向工程,JOOQ還可以用Java代碼來編寫SQL語句,利用IDE的代碼自動補全功能,自動提示表名和字段名,減少程序員記憶負擔,還可以在元數(shù)據(jù)發(fā)生變化時發(fā)生編譯錯誤,提示程序員修改相應的SQL語句。Ebean作為一種基于JPA的框架,它也使用JPQL語言進行查詢,多數(shù)情況下會讓人很惱火。但據(jù)說Ebean不排斥SQL,可以直接用SQL查詢,也可以用類似JOOQ的DSL方式在代碼中構(gòu)造SQL語句(還是JPQL語句?),但沒用過Ebean,所以具體細節(jié)不清楚。在公眾號后端頂級架構(gòu)師后臺回復“架構(gòu)整潔”,獲取一份驚喜禮包。JDBCTemplate就不用說了,它根本沒做ORM,當然是純SQL查詢。利用Spring框架,可以把JDBCTemplate和JPA結(jié)合起來使用,在JPA不好查詢的地方,或者效率低不好優(yōu)化的地方使用JDBC,緩解了Hibernate/JPA封裝SQL造成的麻煩,但我仍沒看到任何封裝SQL的必要性,除了給程序員帶來一大堆麻煩和學習負擔之外,沒有太明顯的好處。二、DSL和變化適應性為了實現(xiàn)復雜的業(yè)務邏輯,不論是用SQL還是hql或者JPQL,我們都不得不寫很多簡單的或者復雜的查詢語句,ORM無法減少這部分工作,最多是用另一種面向?qū)ο箫L格的語言去表達查詢需求,如前所述,用面向?qū)ο箫L格的語言不見得比SQL更容易。通常業(yè)務系統(tǒng)中會有很多表,每個表都有很多字段,即便是編寫最簡單的查詢語句也不是一件容易的事情,需要記住數(shù)據(jù)庫中有哪些表,有哪些字段,記住有哪些函數(shù)等。寫查詢語句很多時候成為一件頭疼的事情。QueryDSL、JOOQ、Ebean甚至MyBatis和JPA都設計一些特性,幫助開發(fā)人員編寫查詢語句,有人稱之為“DSL風格數(shù)據(jù)庫編程”。最早實現(xiàn)這類功能的可能是QueryDSL,把數(shù)據(jù)庫的表結(jié)構(gòu)逆向工程為java的類,然后可以讓java程序員能夠用java的語法構(gòu)造出一個復雜的查詢語句,利用IDE的代碼自動補全功能,可以自動提示表名、字段名、查詢語句的關(guān)鍵字等,很成功的簡化了查詢語句的編寫,免除了程序員記憶各種名字、函數(shù)和關(guān)鍵字的負擔。QueryDSL有很多版本,但用得多的是QueryDSLJPA,可以幫助開發(fā)人員編寫JPQL語句,如前所述,JPQL語句有很多局限不如SQL靈活高效。后來的JOOQ和Ebean,基本上繼承了QueryDSL的思路,Ebean基本上還是JPA風格的ORM框架,雖然也支持SQL,但不清楚其DSL特性是否支持SQL語句編寫,在官網(wǎng)上看到的例子都是用于構(gòu)造JPQL語句。這里面最成功的應該是JOOQ,和QueryDSL不同,JOOQ的DSL編程是幫助開發(fā)人員編寫SQL語句,拋棄累贅的ORM概念,JOOQ這個功能非常輕小,非常容易學習和使用,同時性能也非常好,不像QueryDSL和Ebean,需要了解復雜的JPA概念和各種奇異的限制,JOOQ編寫的就是普通的SQL語句,只是把查詢結(jié)果填充到實體類中(嚴格說JOOQ沒有實體類,只是自動生成的Record對象),JOOQ甚至不一定要把結(jié)果轉(zhuǎn)換為實體類,可以讓開發(fā)人員按照字段取得結(jié)果的值,相對于JDBC,JOOQ會把結(jié)果值轉(zhuǎn)換為合適的Java類型,用起來比JDBC更簡單。傳統(tǒng)主流的框架對DSL風格支持得很少,Hibernate里面基本上沒有看到有這方面的特性。MyBatis提供了"SQL語句構(gòu)建器"來幫助開發(fā)人員構(gòu)造SQL語句,但和QueryDSL/JOOQ/Ebean差很多,不能提示表名和字段名,語法也顯得累贅不像SQL。JPA給人的印象是復雜難懂,它的MetaModelApi繼承了特點,MetaModelAPI+CriteriaAPI,再配合HibernateJPA2MetamodelGenerator,讓人有點QueryDSLJPA的感覺,只是繞了一個大大的彎,疊加了好幾層技術(shù),最后勉強實現(xiàn)了QueryDSLJPA的簡單易懂的功能。很多人不推薦JPA+QueryDSL的用法,而是推薦JPAMetaModelAPI+CriteriaAPI+HibernateJPA2MetamodelGenerator的用法,讓人很難理解,也許是因為這個方案是純的標準的JPA方案。數(shù)據(jù)庫DSL編程的另一個主要賣點是變化適應性強,數(shù)據(jù)庫表結(jié)構(gòu)在開發(fā)過程中通常會頻繁發(fā)生變化,傳統(tǒng)的非DSL編程,字段名只是一個字符串,如果字段名或者類型改變之后,查詢語句沒有相應修改,編譯不會出錯,也容易被開發(fā)人員忽略,是bug的一個主要。DSL編程里面,字段被逆向工程為一個java類的屬性,數(shù)據(jù)庫結(jié)構(gòu)改變之后,作為java代碼一部分的查詢語句會發(fā)生編譯錯誤,提示開發(fā)人員進行修改,可以減少大量bug,減輕測試的負擔,提高軟件的可靠性和質(zhì)量。三、跨數(shù)據(jù)庫移植Hibernate和JPA使用hql和JPQL這類數(shù)據(jù)庫無關(guān)的中間語言描述查詢,可以在不同數(shù)據(jù)庫中無縫移植,移植到一個SQL有巨大差別的數(shù)據(jù)庫通常不需要修改代碼或者只需要修改很少的代碼。Ebean如果不使用原生SQL,而是使用JPA的方式開發(fā),也能在不同數(shù)據(jù)庫中平滑的移植。MyBatis和JOOQ直接使用SQL,跨數(shù)據(jù)庫移植時都難免要修改SQL語句。這方面MyBatis比較差,只有一個動態(tài)SQL提供的特性,對于不同的數(shù)據(jù)庫編寫不同的sql語句。JOOQ雖然無法像Hibernate和JPA那樣無縫移植,但比MyBatis好很多。JOOQ的DSL很大一部分是通用的,例如分頁查詢中,Mysql的limit/offset關(guān)鍵字是很方便的描述方式,但Oracle和SQLServer的SQL不支持,如果我們用JOOQ的DSL的limit和offset方法構(gòu)造SQL語句,不修改移植到不支持limit/offset的Oracle和SQLServer上,我們會發(fā)現(xiàn)這些語句還能正常使用,因為JOOQ會把limit/offset轉(zhuǎn)換成等價的目標數(shù)據(jù)庫的SQL語句。JOOQ根據(jù)目標數(shù)據(jù)庫轉(zhuǎn)換SQL語句的特性,使得在不同數(shù)據(jù)庫之間移植的時候,只需要修改很少的代碼,明顯優(yōu)于MyBatis。JDBCTemplate應該最差,只能盡量使用標準sql語句來減少移植工作量。四、安全性一般來說,拼接查詢語句都會有安全隱患,容易被sql注入攻擊。不論是jdbc,還是hql/JPQL,只要使用拼接的查詢語句都是不安全的。對于JDBC來說,使用參數(shù)化的sql語句代替拼接,可以解決問題。而JPA則應該使用CriteriaAPI解決這個問題。對于JOOQ之類的DSL風格框架,最終會被render為參數(shù)化的sql,天生免疫sql注入攻擊。Ebean也支持DSL方式編程,也同樣免疫sql注入攻擊。這是因為DSL風格編程參數(shù)化查詢比拼接字符串查詢更簡單,沒人會拼接字符串。而jdbc/hql/JPQL拼接字符串有時候比參數(shù)化查詢更簡單,特別是jdbc,很多人會偷懶使用不安全的方式。五、JOOQ的失敗之處可能大部分人會不同意,雖然Hibernate、JPA仍然大行其道,是最主流的持久化框架,但其實這種封裝SQL的純正ORM已經(jīng)過時,效益低于使用它們的代價,應該淘汰了。MyBatis雖然有很多優(yōu)點,但它的優(yōu)點JOOQ基本上都有,而且

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論