Posted on 2006-03-02 20:58
killvin 閱讀(428)
評論(0) 編輯 收藏 所屬分類:
java
該文轉自guty
O-R Mapping
J2EE的標準是CMP Entity Bean,而實際應用中受到詬病最多的也是它。我們化了整整半年時間研究CMP2.0的開發方法,目前總算能夠將代碼量減少到70%,并且有希望減少到 90%。我曾經很滿足現有的成績,但是當我真正地閱讀了hibernate后,對CMP2.0的信心徹底動搖了。
hibernate至少比CMP2.0有以下優點:
1. 兼容性。 規范一模一樣,實現各有不同,這是CMP的現狀。用第三方O-R Mapping工具可以解決這個問題。
2. 保護智力投資。在了解了Orion, Weblogic, JBoss的CMP實現后,我不愿意再去學習Websphere 或者Resin的實現了。
3. 性能。
a. local v.s. remote, hibernate、JDO、Castor都是本地調用,CMP2.0雖然也有Local接口,但是Web層還是需要通過Remote接口訪問EJB層的數據,序列化、網絡調用、創建大量的對象,都是性能降低的原因。
b. transaction,J2EE提出了一個全新的事務模型(method-based descriptor),對程序員的開發確實是個“簡化”,記得一本教程建議所有的EJB方法都用Required。但這樣的結果是什么?性能極度降低!互鎖!沒有辦法,我們只有再去調節各個方法的Transaction屬性,然后又出現 新的互鎖...
新的事務模型是不成功的。它試圖簡化問題,卻引入了更為嚴重的問題。各家廠商的Transaction實現也不盡相同,有的支持Optimistic Lock,有的在VM中同步Entity對象,又是兼容性的一大敵。
hibernate沒有試圖創造一個更新的模式,相反,它沿用了傳統數據庫的Transaction編程模式,在對J2EE的Transaction傷透腦筋后看到它,真是十分親切,感覺自己確實在編程,而不是碰運氣填代碼了。
4. 動態Query。
Entity Bean很難實現動態Query,這是因為它基于代碼自動生成技術,即最終的執行代碼是在部署編譯時生成的。hibernate則有根本的改變,它基于 reflection機制,運行時動態Query是很自然的事。另外,hibernate幾乎支持所有的SQL語法,傳統數據庫可以做的它就可以做。
5. 發展速度。
I have a dream, 有一天Entity Bean會變得很好。但至少目前來看,Entity Bean是一個不完善的產品,它是大公司政治斗爭和妥協的產品,而且習慣性將一些問題“無限期擱置”,典型的例子就是Query(之所以不提其他問題,是因為其他都是Entity Bean的致命傷:))
形成強烈反差的是,hibernate的核心程序員只有一人,但它改進的速度確是Entity Bean無法企及的。
6. 繼承和多態。
OO語言的精華在Entity Bean這里是行不通的,我曾經自我安慰將Entity Bean看做一個“內存中的數據表”,才找到了一點平衡。
但當我看到hibernate時,又開始不平衡了。
另外,CMP2.0也有一些缺點是可以彌補的。
1. 代碼維護。
大量的接口文件和配置文件,開發和維護的工作量很大。
解決途徑:采用xdoclet,可以自動產生眾多的接口和配置文件,甚至facade, delegate等高級模式。
至少目前來看,hibernate的缺點有:
1. 代碼維護
hibernate提供了自動生成mapping文件“框架”的工具,但還需要手工調節。而這類開發,能想到的最佳模式就是xdoclet的(代碼+注釋)的模式了。幸好,hibernate的程序員已經向xdoclet項目增加了hibernate的模塊。現在需要的是等待xdoclet的下一個 release。
結論:
hibernate至少從文檔上超越了Entity Bean很多,我要學習hibernate。
以下是robbin的觀點
如果說不使用Session Facade模式的話,我認為EB還是一個很有意義的的東西,因為EB是唯一直接支持跨RMI的持久化方案。但是由于EB的效率和減少跨RMI的網絡調用的原因,EB已經完全被封裝到SB的后面,EB的分布式調用的功能,EB的安全驗證功能,EB的容器事務功能完全被前面的SB給做了,結果EB就只剩下了唯一的ORM功能了,單就ORM這一點來說EB實在是一個非常非常糟糕的東西。那么EB還有什么功能值得我非去用它不可呢?
用 Session Bean + DAO + Hibernate 來取代 Session Bean + Entity Bean,不但能夠極大降低軟件設計難度,軟件開發難度,軟件調試難度和軟件部署難度,而且還可以提高允許效率,降低硬件要求。
不要把EB直接拿來和Hibernate做比較,兩者不是一個范疇的東西,而應該整體比較兩種方案:
Session Bean + DAO + Hibernate
Session Bean + Entity Bean
我找不出來第二方案有哪怕一點方面能夠比第一方案好的。
CMP可以使用CMR來表示多表之間通過外鍵關聯的關系。但是你仍然會遇到即使沒有鍵關聯的表仍然需要連接查詢的情況,這是一個非常普遍的現象。
如果是Hibernate,可以在HSQL里面定義outer join,BMP也可以寫JDBC,而CMP沒有任何辦法來解決該問題,除非你把需要的連接查詢都定義為CMR,但那樣的話,凡是有需要連接查詢,或者有鍵關聯的表都必須打在一個包里面。你如果不打在一個jar包里面,如果能夠建立CMR?不是我想放在一個jar里面,而是不得不放在一個jar里面。基本上CMP還是非常笨拙的。
CMP的另一大缺點是不能動態SQL,guty已經提到了,一個SQL就要定義一個EJBFinder方法,在編譯的時候就確定死了。在實際應用中,經常會遇到不確定查詢條件的查詢,比如說用戶在頁面上用下拉列表來選擇查詢的條件,用戶既有可能什么限制條件都不選,也有可能選擇某幾個條件。這時候你怎么辦?假設有n個查詢條件,你要寫 C1n + C2n + C3n +...+ Cnn(C是組合公式的符合,n是下標,1...n是上標)個EJBFinder方法才行,很恐怖吧。
其實JDBC的PrepareStatement也不能很好的解決這個問題,因為它是按照1,2這樣的次序來set參數的。用Statement是肯定不行的,會嚴重影響數據庫,甚至會導致數據庫down掉(我的實際經驗)。但是Hibernate就解決的不錯,因為它可以按照 :name 這樣的形式來設定SQL中的Placeholder,這樣set參數就可以按照參數名稱傳遞,因為次序不是死的,在程序里面就很容易根據用戶選擇的查詢條件,動態的產生SQL,動態的set參數了。
CMP2.0還有一個大問題是不支持order by,當然你可以在Java里面對取出來的集合排序,但是速度和數據庫里面就排好序速度不在一個數量級了。Hibernate不但可以order by,還可以group by,having,子查詢,真是沒有辦法比下去了。
其實對于動態SQL和排序問題,特定的App Server也可以做,但那不是CMP2.0的規范罷了,所以為了可移植性,也不敢隨便去用。
在項目開發時, 開發和運行效率以及靈活性是非常重要的指標。由于Entity Bean天生是一種粗粒度的使用方式,這就必定使它在裝載的時候有較長的響應時間,也不能自如的支持懶裝入的方式,使用成細粒度會使程序變得復雜,以及遠程調用細粒度的entity bean是一種非常可怕的行為, 太慢了.
Hibernate正好滿足開發和運行效率以及靈活性,說來說去,它可以稱做一個OO化的JDBC, 這樣大家就不會對Hibernate產生誤解及恐懼心理。它支持粗細兩種粒度方式,運用起來靈活自如,前提是你必知道如何使用,一個entity bean 實現要N種重復的方法, such as ejbRemove,ejbstore,ejb...., 光類也有一大堆,象Home Interface, Romote Interface..., Primary class if necessary. Hibernate只需要一個就行了。
CMP在進行O/R Mapping方面只是做了最基礎的工作而已,完全用CMP做數據層,會發現你在把數據庫應該做的工作全部都搬到App Server里面來重新實現一遍,有這必要嗎?
CMP是把EJBQL寫死在ejb-jar.xml里面的,所以n個條件就需要(c0n+c1n+...cnn )2的n次方個EJBFinder方法,簡直沒有辦法說。
JDBC實現PrepareStatement的動態SQL構造不是不能夠,而是非常麻煩,需要寫一個非常非常大的if elseif else嵌套的判斷。
Hibernate實現起來特別簡單,(其實OJB也實現了PrepareStatement的動態SQL構造)這本身并不復雜,但是需要你多寫些代碼而已,由于CMP把EJBQL寫死在配置文件里面了,你連選擇的余地都沒有。