Entity Bean vs Hibernate Pojo

          Posted on 2006-03-02 20:58 killvin 閱讀(434) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): java

          該文轉(zhuǎn)自guty

          O-R Mapping

          J2EE的標(biāo)準(zhǔn)是CMP Entity Bean,而實(shí)際應(yīng)用中受到詬病最多的也是它。我們化了整整半年時(shí)間研究CMP2.0的開(kāi)發(fā)方法,目前總算能夠?qū)⒋a量減少到70%,并且有希望減少到 90%。我曾經(jīng)很滿(mǎn)足現(xiàn)有的成績(jī),但是當(dāng)我真正地閱讀了hibernate后,對(duì)CMP2.0的信心徹底動(dòng)搖了。

          hibernate至少比CMP2.0有以下優(yōu)點(diǎn):
          1. 兼容性。 規(guī)范一模一樣,實(shí)現(xiàn)各有不同,這是CMP的現(xiàn)狀。用第三方O-R Mapping工具可以解決這個(gè)問(wèn)題。
          2. 保護(hù)智力投資。在了解了Orion, Weblogic, JBoss的CMP實(shí)現(xiàn)后,我不愿意再去學(xué)習(xí)Websphere 或者Resin的實(shí)現(xiàn)了。
          3. 性能。
          a. local v.s. remote, hibernate、JDO、Castor都是本地調(diào)用,CMP2.0雖然也有Local接口,但是Web層還是需要通過(guò)Remote接口訪問(wèn)EJB層的數(shù)據(jù),序列化、網(wǎng)絡(luò)調(diào)用、創(chuàng)建大量的對(duì)象,都是性能降低的原因。
          b. transaction,J2EE提出了一個(gè)全新的事務(wù)模型(method-based descriptor),對(duì)程序員的開(kāi)發(fā)確實(shí)是個(gè)“簡(jiǎn)化”,記得一本教程建議所有的EJB方法都用Required。但這樣的結(jié)果是什么?性能極度降低!互鎖!沒(méi)有辦法,我們只有再去調(diào)節(jié)各個(gè)方法的Transaction屬性,然后又出現(xiàn) 新的互鎖...
          新的事務(wù)模型是不成功的。它試圖簡(jiǎn)化問(wèn)題,卻引入了更為嚴(yán)重的問(wèn)題。各家廠商的Transaction實(shí)現(xiàn)也不盡相同,有的支持Optimistic Lock,有的在VM中同步Entity對(duì)象,又是兼容性的一大敵。
          hibernate沒(méi)有試圖創(chuàng)造一個(gè)更新的模式,相反,它沿用了傳統(tǒng)數(shù)據(jù)庫(kù)的Transaction編程模式,在對(duì)J2EE的Transaction傷透腦筋后看到它,真是十分親切,感覺(jué)自己確實(shí)在編程,而不是碰運(yùn)氣填代碼了。
          4. 動(dòng)態(tài)Query。
          Entity Bean很難實(shí)現(xiàn)動(dòng)態(tài)Query,這是因?yàn)樗诖a自動(dòng)生成技術(shù),即最終的執(zhí)行代碼是在部署編譯時(shí)生成的。hibernate則有根本的改變,它基于 reflection機(jī)制,運(yùn)行時(shí)動(dòng)態(tài)Query是很自然的事。另外,hibernate幾乎支持所有的SQL語(yǔ)法,傳統(tǒng)數(shù)據(jù)庫(kù)可以做的它就可以做。
          5. 發(fā)展速度。
          I have a dream, 有一天Entity Bean會(huì)變得很好。但至少目前來(lái)看,Entity Bean是一個(gè)不完善的產(chǎn)品,它是大公司政治斗爭(zhēng)和妥協(xié)的產(chǎn)品,而且習(xí)慣性將一些問(wèn)題“無(wú)限期擱置”,典型的例子就是Query(之所以不提其他問(wèn)題,是因?yàn)槠渌际荅ntity Bean的致命傷:))
          形成強(qiáng)烈反差的是,hibernate的核心程序員只有一人,但它改進(jìn)的速度確是Entity Bean無(wú)法企及的。
          6. 繼承和多態(tài)。
          OO語(yǔ)言的精華在Entity Bean這里是行不通的,我曾經(jīng)自我安慰將Entity Bean看做一個(gè)“內(nèi)存中的數(shù)據(jù)表”,才找到了一點(diǎn)平衡。
          但當(dāng)我看到hibernate時(shí),又開(kāi)始不平衡了。

          另外,CMP2.0也有一些缺點(diǎn)是可以彌補(bǔ)的。
          1. 代碼維護(hù)。
          大量的接口文件和配置文件,開(kāi)發(fā)和維護(hù)的工作量很大。
          解決途徑:采用xdoclet,可以自動(dòng)產(chǎn)生眾多的接口和配置文件,甚至facade, delegate等高級(jí)模式。

          至少目前來(lái)看,hibernate的缺點(diǎn)有:
          1. 代碼維護(hù)
          hibernate提供了自動(dòng)生成mapping文件“框架”的工具,但還需要手工調(diào)節(jié)。而這類(lèi)開(kāi)發(fā),能想到的最佳模式就是xdoclet的(代碼+注釋?zhuān)┑哪J搅?。幸好,hibernate的程序員已經(jīng)向xdoclet項(xiàng)目增加了hibernate的模塊。現(xiàn)在需要的是等待xdoclet的下一個(gè) release。

          結(jié)論:
          hibernate至少?gòu)奈臋n上超越了Entity Bean很多,我要學(xué)習(xí)hibernate。

          以下是robbin的觀點(diǎn)

          如果說(shuō)不使用Session Facade模式的話(huà),我認(rèn)為EB還是一個(gè)很有意義的的東西,因?yàn)镋B是唯一直接支持跨RMI的持久化方案。但是由于EB的效率和減少跨RMI的網(wǎng)絡(luò)調(diào)用的原因,EB已經(jīng)完全被封裝到SB的后面,EB的分布式調(diào)用的功能,EB的安全驗(yàn)證功能,EB的容器事務(wù)功能完全被前面的SB給做了,結(jié)果EB就只剩下了唯一的ORM功能了,單就ORM這一點(diǎn)來(lái)說(shuō)EB實(shí)在是一個(gè)非常非常糟糕的東西。那么EB還有什么功能值得我非去用它不可呢?

          用 Session Bean + DAO + Hibernate 來(lái)取代 Session Bean + Entity Bean,不但能夠極大降低軟件設(shè)計(jì)難度,軟件開(kāi)發(fā)難度,軟件調(diào)試難度和軟件部署難度,而且還可以提高允許效率,降低硬件要求。

          不要把EB直接拿來(lái)和Hibernate做比較,兩者不是一個(gè)范疇的東西,而應(yīng)該整體比較兩種方案:
          Session Bean + DAO + Hibernate
          Session Bean + Entity Bean
          我找不出來(lái)第二方案有哪怕一點(diǎn)方面能夠比第一方案好的。

          CMP可以使用CMR來(lái)表示多表之間通過(guò)外鍵關(guān)聯(lián)的關(guān)系。但是你仍然會(huì)遇到即使沒(méi)有鍵關(guān)聯(lián)的表仍然需要連接查詢(xún)的情況,這是一個(gè)非常普遍的現(xiàn)象。

          如果是Hibernate,可以在HSQL里面定義outer join,BMP也可以寫(xiě)JDBC,而CMP沒(méi)有任何辦法來(lái)解決該問(wèn)題,除非你把需要的連接查詢(xún)都定義為CMR,但那樣的話(huà),凡是有需要連接查詢(xún),或者有鍵關(guān)聯(lián)的表都必須打在一個(gè)包里面。你如果不打在一個(gè)jar包里面,如果能夠建立CMR?不是我想放在一個(gè)jar里面,而是不得不放在一個(gè)jar里面。基本上CMP還是非常笨拙的。

          CMP的另一大缺點(diǎn)是不能動(dòng)態(tài)SQL,guty已經(jīng)提到了,一個(gè)SQL就要定義一個(gè)EJBFinder方法,在編譯的時(shí)候就確定死了。在實(shí)際應(yīng)用中,經(jīng)常會(huì)遇到不確定查詢(xún)條件的查詢(xún),比如說(shuō)用戶(hù)在頁(yè)面上用下拉列表來(lái)選擇查詢(xún)的條件,用戶(hù)既有可能什么限制條件都不選,也有可能選擇某幾個(gè)條件。這時(shí)候你怎么辦?假設(shè)有n個(gè)查詢(xún)條件,你要寫(xiě) C1n + C2n + C3n +...+ Cnn(C是組合公式的符合,n是下標(biāo),1...n是上標(biāo))個(gè)EJBFinder方法才行,很恐怖吧。

          其實(shí)JDBC的PrepareStatement也不能很好的解決這個(gè)問(wèn)題,因?yàn)樗前凑?,2這樣的次序來(lái)set參數(shù)的。用Statement是肯定不行的,會(huì)嚴(yán)重影響數(shù)據(jù)庫(kù),甚至?xí)?dǎo)致數(shù)據(jù)庫(kù)down掉(我的實(shí)際經(jīng)驗(yàn))。但是Hibernate就解決的不錯(cuò),因?yàn)樗梢园凑?:name 這樣的形式來(lái)設(shè)定SQL中的Placeholder,這樣set參數(shù)就可以按照參數(shù)名稱(chēng)傳遞,因?yàn)榇涡虿皇撬赖?,在程序里面就很容易根?jù)用戶(hù)選擇的查詢(xún)條件,動(dòng)態(tài)的產(chǎn)生SQL,動(dòng)態(tài)的set參數(shù)了。

          CMP2.0還有一個(gè)大問(wèn)題是不支持order by,當(dāng)然你可以在Java里面對(duì)取出來(lái)的集合排序,但是速度和數(shù)據(jù)庫(kù)里面就排好序速度不在一個(gè)數(shù)量級(jí)了。Hibernate不但可以order by,還可以group by,having,子查詢(xún),真是沒(méi)有辦法比下去了。

          其實(shí)對(duì)于動(dòng)態(tài)SQL和排序問(wèn)題,特定的App Server也可以做,但那不是CMP2.0的規(guī)范罷了,所以為了可移植性,也不敢隨便去用。

          在項(xiàng)目開(kāi)發(fā)時(shí), 開(kāi)發(fā)和運(yùn)行效率以及靈活性是非常重要的指標(biāo)。由于Entity Bean天生是一種粗粒度的使用方式,這就必定使它在裝載的時(shí)候有較長(zhǎng)的響應(yīng)時(shí)間,也不能自如的支持懶裝入的方式,使用成細(xì)粒度會(huì)使程序變得復(fù)雜,以及遠(yuǎn)程調(diào)用細(xì)粒度的entity bean是一種非??膳碌男袨? 太慢了.

          Hibernate正好滿(mǎn)足開(kāi)發(fā)和運(yùn)行效率以及靈活性,說(shuō)來(lái)說(shuō)去,它可以稱(chēng)做一個(gè)OO化的JDBC, 這樣大家就不會(huì)對(duì)Hibernate產(chǎn)生誤解及恐懼心理。它支持粗細(xì)兩種粒度方式,運(yùn)用起來(lái)靈活自如,前提是你必知道如何使用,一個(gè)entity bean 實(shí)現(xiàn)要N種重復(fù)的方法, such as ejbRemove,ejbstore,ejb...., 光類(lèi)也有一大堆,象Home Interface, Romote Interface..., Primary class if necessary. Hibernate只需要一個(gè)就行了。

          CMP在進(jìn)行O/R Mapping方面只是做了最基礎(chǔ)的工作而已,完全用CMP做數(shù)據(jù)層,會(huì)發(fā)現(xiàn)你在把數(shù)據(jù)庫(kù)應(yīng)該做的工作全部都搬到App Server里面來(lái)重新實(shí)現(xiàn)一遍,有這必要嗎?

          CMP是把EJBQL寫(xiě)死在ejb-jar.xml里面的,所以n個(gè)條件就需要(c0n+c1n+...cnn )2的n次方個(gè)EJBFinder方法,簡(jiǎn)直沒(méi)有辦法說(shuō)。

          JDBC實(shí)現(xiàn)PrepareStatement的動(dòng)態(tài)SQL構(gòu)造不是不能夠,而是非常麻煩,需要寫(xiě)一個(gè)非常非常大的if elseif else嵌套的判斷。

          Hibernate實(shí)現(xiàn)起來(lái)特別簡(jiǎn)單,(其實(shí)OJB也實(shí)現(xiàn)了PrepareStatement的動(dòng)態(tài)SQL構(gòu)造)這本身并不復(fù)雜,但是需要你多寫(xiě)些代碼而已,由于CMP把EJBQL寫(xiě)死在配置文件里面了,你連選擇的余地都沒(méi)有。

          主站蜘蛛池模板: 格尔木市| 轮台县| 樟树市| 镇平县| 博白县| 屯昌县| 于都县| 镇原县| 亚东县| 普安县| 辽阳县| 霞浦县| 隆子县| 洛隆县| 开江县| 安陆市| 都匀市| 达孜县| 都兰县| 昌宁县| 礼泉县| 梓潼县| 顺义区| 吴旗县| 南阳市| 高安市| 莫力| 洱源县| 连江县| 永春县| 叶城县| 富民县| 专栏| 通辽市| 越西县| 汉中市| 武强县| 晋江市| 宜州市| 长宁县| 汽车|