為什么要學(xué)習(xí)Hibernate?
發(fā)表時(shí)間:2024-05-30 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]在我做過(guò)的很多項(xiàng)目的過(guò)程中,我一直有一個(gè)懸而未決的問(wèn)題在困擾我,那就是持久層的開(kāi)發(fā)。持久層的開(kāi)發(fā)一般來(lái)說(shuō)要么用CMP,要么用JDBC+DAO。 CMP就不用說(shuō)了,它對(duì)我來(lái)說(shuō)是一種失敗的實(shí)踐,而JDBC+DAO也存在很多的困難,我很難做到把關(guān)系表記錄完整的映射到持久對(duì)象的關(guān)系上來(lái),這主要體現(xiàn)在多表的...
在我做過(guò)的很多項(xiàng)目的過(guò)程中,我一直有一個(gè)懸而未決的問(wèn)題在困擾我,那就是持久層的開(kāi)發(fā)。持久層的開(kāi)發(fā)一般來(lái)說(shuō)要么用CMP,要么用JDBC+DAO。 CMP就不用說(shuō)了,它對(duì)我來(lái)說(shuō)是一種失敗的實(shí)踐,而JDBC+DAO也存在很多的困難,我很難做到把關(guān)系表記錄完整的映射到持久對(duì)象的關(guān)系上來(lái),這主要體現(xiàn)在多表的關(guān)系無(wú)法直接映射到對(duì)持久對(duì)象的映射上來(lái),可能是一個(gè)表映射多個(gè)持久對(duì)象,有可能是多個(gè)表映射一個(gè)持久對(duì)象,更有可能的是表的某些字段映射到一個(gè)持久對(duì)象,但是另外一些字段映射到別的持久對(duì)象上。而且即使這些問(wèn)題都處理好了,也不能直接按照對(duì)象的方式來(lái)對(duì)持久對(duì)象(PO)編程,因?yàn)榇嬖?:N關(guān)系的持久對(duì)象的查詢(xún)其實(shí)就是1+n次對(duì)數(shù)據(jù)庫(kù)的SQL,我曾經(jīng)有一次失敗的持久層設(shè)計(jì),結(jié)果是某個(gè)關(guān)聯(lián)很多其它持久對(duì)象的PO一查詢(xún)就是5n+1次 sql,速度慢的不得了,最后不得不整個(gè)修改底層設(shè)計(jì),最后等于是完全拋棄了對(duì)象設(shè)計(jì),完全是按照表字段進(jìn)行操作。
但是這樣做非常難受,因?yàn)橄到y(tǒng)的設(shè)計(jì)是從需求設(shè)計(jì),系統(tǒng)設(shè)計(jì)這樣自頂而下的,結(jié)果都到了詳細(xì)設(shè)計(jì)階段了,被持久層映射問(wèn)題限制,不得不自底向上修改設(shè)計(jì)方案,又回到了按照過(guò)程進(jìn)行編程的老路上來(lái),非常的糟糕。
我對(duì)這個(gè)問(wèn)題思考了很久,最后終于意識(shí)到這其實(shí)是一個(gè)很經(jīng)典的問(wèn)題:對(duì)象和關(guān)系的映射問(wèn)題。實(shí)際上自從OOP編程流行以后,就存在這個(gè)難題了,所以才有人提出關(guān)系數(shù)據(jù)庫(kù)進(jìn)行重新設(shè)計(jì),改用對(duì)象數(shù)據(jù)庫(kù),但實(shí)際上關(guān)系數(shù)據(jù)庫(kù)并沒(méi)有被淘汰,于是就只能在上層的應(yīng)用層找解決方案。這時(shí)候我明白了我需要的實(shí)際上是一種 ORM產(chǎn)品。
我最早想到的ORM就是JDO,于是我下載了兩個(gè)JDO產(chǎn)品,準(zhǔn)備認(rèn)真的學(xué)習(xí)一下,但是研究了一段時(shí)間之后,我發(fā)現(xiàn)我對(duì)JDO非常的失望,原因如下:
1、 JDO沒(méi)有一個(gè)好的開(kāi)源免費(fèi)實(shí)現(xiàn),好的產(chǎn)品都是商業(yè)產(chǎn)品,并且在國(guó)內(nèi)沒(méi)有銷(xiāo)售和技術(shù)支持。這就造成了JDO只有學(xué)習(xí)之用,不能把它用在實(shí)際項(xiàng)目中,否則的話(huà),你把軟件賣(mài)給客戶(hù)的時(shí)候,還要告訴他,你還要另外去買(mǎi)一個(gè)國(guó)外的軟件產(chǎn)品,并且在國(guó)內(nèi)沒(méi)有技術(shù)支持,出了持久層的問(wèn)題,我們也解決不了,請(qǐng)你自己打國(guó)際長(zhǎng)途去解決問(wèn)題,你認(rèn)為客戶(hù)能答應(yīng)嗎?
2、JDO不是一個(gè)輕量級(jí)封裝,它試圖建立一個(gè)完整的持久層框架,但是還很不完善,造成了JDO 感覺(jué)比較笨重,很多操作方式令人覺(jué)得煩瑣和古怪。這加重了程序員學(xué)習(xí)和編程的負(fù)擔(dān),而且封裝的太多會(huì)造成一個(gè)嚴(yán)重的問(wèn)題就是一旦出現(xiàn)報(bào)錯(cuò)信息,調(diào)試起來(lái)非常困難,你很難準(zhǔn)確的定位錯(cuò)誤究竟出在哪里,封裝的越輕,問(wèn)題越容易定位,越容易解決,封裝的越重,問(wèn)題越復(fù)雜,越找不到原因,CMP就是一個(gè)很好的例子,出了錯(cuò)誤,調(diào)試起來(lái)非常困難和麻煩。
3、JDO的標(biāo)準(zhǔn)很不完善,存在重大缺陷。最主要的問(wèn)題體現(xiàn)在PO不能脫離PM(相當(dāng)于 Hibernate的Session)而存在,這是個(gè)非常嚴(yán)重的問(wèn)題,會(huì)造成編程的時(shí)候進(jìn)行大量VO的拷貝操作,煩瑣極了;另外一個(gè)重大缺陷是靜態(tài)的 POJO的Enhancer,不能運(yùn)行期動(dòng)態(tài)Enhance,無(wú)法進(jìn)行增量編譯和調(diào)試,編程和調(diào)試起來(lái)非常煩瑣,每次都要手共運(yùn)行一個(gè)工具對(duì)POJO進(jìn)行 Enhance;此外還有一些缺陷,例如JDOQL不完善,映射關(guān)系的表達(dá)不夠強(qiáng)大等等。
4、JDO產(chǎn)品的分裂。這個(gè)問(wèn)題也比較嚴(yán)重,由于JDO1.0標(biāo)準(zhǔn)的缺陷,而JDO2.0標(biāo)準(zhǔn)還遙遙無(wú)期,而各個(gè)JDO廠商為了能夠在競(jìng)爭(zhēng)中脫穎而出,那么除了在易操作性和性能上的提高之外,想要吸引客戶(hù),就必須有自己的產(chǎn)品特色。那么1.0標(biāo)準(zhǔn)的缺陷正好給了他們發(fā)揮的舞臺(tái),每個(gè)廠商都會(huì)有自己獨(dú)到的解決方案來(lái)解決標(biāo)準(zhǔn)的缺陷,然而這卻造成了JDO 產(chǎn)品事實(shí)上的分裂。這種分裂嚴(yán)重到什么程度?我可以簡(jiǎn)單舉個(gè)例子:你寫(xiě)好的POJO,用一種JDO的Enhancer進(jìn)行Enhance過(guò)以后得到的 PO,在另一個(gè)JDO產(chǎn)品上跑不起來(lái)。這很像當(dāng)年Unix的分裂,結(jié)果就是二進(jìn)制代碼級(jí)的不兼容,而只能在C源代碼級(jí)兼容,F(xiàn)在的JDO也有這樣的趨勢(shì),就像App Server的差別一樣,一個(gè)在Weblogic上開(kāi)發(fā)好的EJB,移植到Websphere,你一定需要重新進(jìn)行配置。
我心目中的ORM最好有如下的特點(diǎn):
1、開(kāi)源和免費(fèi)的License,我可以在需要的時(shí)候研究源代碼,改寫(xiě)源代碼,進(jìn)行功能的定制。
2、輕量級(jí)封裝,避免引入過(guò)多復(fù)雜的問(wèn)題,調(diào)試容易,也減輕程序員的負(fù)擔(dān)。
3、具有可擴(kuò)展性,API開(kāi)放,當(dāng)本身功能不夠用的時(shí)候,可以自己遍碼進(jìn)行擴(kuò)展。
4、開(kāi)發(fā)者活躍,產(chǎn)品有穩(wěn)定的發(fā)展保障。
拋棄了JDO以后,我根據(jù)上面的原則,先后排除了TopLink,CocoBase,Castor等,最后選擇了Apache OJB和Hibernate。
OJB的排除很容易做出,一是因?yàn)樗奈臋n太簡(jiǎn)單,太少;二是因?yàn)镺JB計(jì)劃下一個(gè)版本全面支持JDO,它的API會(huì)有重大變動(dòng),所以現(xiàn)階段學(xué)習(xí)OJB是個(gè)錯(cuò)誤,等它的API穩(wěn)定了以后再學(xué)習(xí)不遲。
Hibernate的發(fā)現(xiàn)是很偶然的事情,只是在別人提到JDO的產(chǎn)品中,附帶提了提而已,但當(dāng)我開(kāi)始研究Hibernate之后,我發(fā)現(xiàn)終于找到了我夢(mèng)寐以求的ORM了。
Hibernate 完全符合我上面提到的標(biāo)準(zhǔn)之外,也解決掉了JDO的所有缺陷,而且方式之優(yōu)雅令人贊嘆。Hibernate的文檔也是非常非常有特色的地方,它不僅僅是 Hibernate的功能介紹那么簡(jiǎn)單,它實(shí)際上是一個(gè)持久層設(shè)計(jì)的最佳實(shí)踐的經(jīng)驗(yàn)總結(jié),文檔里面的例子,文檔里面的總結(jié)全部都是最佳設(shè)計(jì)的結(jié)晶。我認(rèn)真的把Hibernate讀下來(lái)的感覺(jué)就是,不單單把Hibernate掌握住了,而且對(duì)持久層的設(shè)計(jì)的經(jīng)驗(yàn)都長(zhǎng)了一大塊,以前可從來(lái)沒(méi)有覺(jué)得持久層的設(shè)計(jì)還有那么多的學(xué)問(wèn),也由此感覺(jué)到Gavin絕對(duì)是一個(gè)大牛人。
當(dāng)然選擇Hibernate最最重用的原因是Hibernate是一個(gè)我能夠完完全全駕馭的了的軟件。Hibernate的源代碼非常少,而且寫(xiě)的非常簡(jiǎn)潔,我總覺(jué)得挺奇怪的,這么少的源代碼能夠?qū)崿F(xiàn)這么多的功能,是個(gè)奇跡。 Hibernate的源代碼樹(shù)分的很清楚簡(jiǎn)單,源代碼很易讀,我一旦碰到文檔中沒(méi)有講到的問(wèn)題,或者文檔中提到但是我搞不清楚的地方,我就去源代碼中找,所有的問(wèn)題都豁然開(kāi)朗,而且讓我對(duì)Hibernate的運(yùn)行原理和細(xì)節(jié)搞的特別清楚,好像Hibernate就像自己寫(xiě)的代碼一樣,很清楚的知道,怎么寫(xiě)程序可以讓Hibernate運(yùn)行效率最高,最省內(nèi)存,程序出了錯(cuò)誤,很清楚的知道是什么地方的問(wèn)題,怎么解決。所以用Hibernate讓我特別放心,我能夠駕馭它,而不像那些過(guò)于復(fù)雜的軟件,本身框架就復(fù)雜的很,再加上不開(kāi)源,出了問(wèn)題也不知道怎么回事。
<>