(大量參考PoEAA...-_-...)
最近網(wǎng)上看到這樣的帖子<<誰能告訴我Hibernate有何優(yōu)秀之處>> 作者給出了對hibernate在實現(xiàn)orm的諸多不滿和懷疑。而且很多開發(fā)人員都有著這樣疑問,“怎么這個流行東東,我用起來就是不順手呢?”,“或許這個東東只是用來吹牛的…”。然而,這或許很可能是因為,你習(xí)慣的架構(gòu)模式開發(fā)策略并不適合使用orm這種持久化模式。用了反而是加大復(fù)雜度降低性能和效率。比如,用慣了resultset,喜歡把resultset放在表示層作為展示的數(shù)據(jù)結(jié)構(gòu)的人。這樣的開發(fā)人員因為習(xí)慣了二維表為核心進行開發(fā),對于Hibernate這樣的orm工具根本就沒辦法了解其優(yōu)勢了。但是這并不是說這種以二維表的架構(gòu)模式就比較差了,只是不同的模式有不同的優(yōu)缺點就看所在的應(yīng)用是否適合使用了。或許你就一直在使用這樣的模式在開發(fā)應(yīng)用,自己還沒有意識到(甚至一直以為這樣的方式可以適應(yīng)任何應(yīng)用,:-)。反而被其他架構(gòu)模式中才會用到的框架搞的暈頭轉(zhuǎn)向甚至被誤導(dǎo)。事實上,像前面提到的以二維表為核心的架構(gòu)被稱之為”表模塊”架構(gòu)(設(shè)計)模式。
何為“表模塊”(table module)?“處理某一個數(shù)據(jù)庫表、視圖或虛擬表中所有行為的業(yè)務(wù)邏輯組成的一個實例”。最初,我就是從馬丁同學(xué)的POEAA中得到的這個定義。在書中他被定義在DomainLogic 層次或者該層次的一部分,DomainLogic也就是其他架構(gòu)模型中的BizLogic層。與該模式相對應(yīng)個還有完成相似功能的DomainModel以及TransactionScript模式。該層次的職責(zé)是專門處理業(yè)務(wù)邏輯。
簡單的講,所謂“表模塊”就是以一個類對應(yīng)數(shù)據(jù)庫中一個表(視圖)的數(shù)據(jù)來組織業(yè)務(wù)邏輯。從設(shè)計層次表妙面上看這種結(jié)構(gòu)很像經(jīng)典OO模型,同樣是以不同對象對應(yīng)不同邏輯。但是,它與領(lǐng)域建模不同之處在于,它的對象并不表示一個問題領(lǐng)域?qū)ο笤谲浖到y(tǒng)中的映射。而是表示對一組數(shù)據(jù)的處理邏輯,而通常這組數(shù)據(jù)的結(jié)構(gòu)是重數(shù)據(jù)庫表或試圖上的二維數(shù)據(jù)結(jié)構(gòu)。當(dāng)然也可以來自其他集成部分,比如返回兩位數(shù)據(jù)結(jié)構(gòu)的webservice。
這里給出個比較形象的例子:

(上圖)感覺像比較標準的OO吧,好象一個Contract的對象表示合同,而Product表示產(chǎn)品,還有他們之間的關(guān)聯(lián)關(guān)系。但是其實現(xiàn)實給出幾個方法的時候就看出區(qū)別了。Product內(nèi)部的數(shù)據(jù)其實就是一個兩位結(jié)構(gòu)的rowset。而不像真正的領(lǐng)域模型分析出來的表示一個Product的數(shù)據(jù),Contract也是如此。

你會發(fā)現(xiàn)tableModule的類中一個對象其實對應(yīng)一個表的數(shù)據(jù),其擁有的操作也有很多是多數(shù)據(jù)記錄的。多數(shù)據(jù)記錄的操作在真正的領(lǐng)域中往往應(yīng)該放在類似Manager這樣的實體中,而不是業(yè)務(wù)實體本身。
使用這種模式實現(xiàn)的業(yè)務(wù)邏輯層不像領(lǐng)域模型模式可以適應(yīng)搞復(fù)雜度的邏輯。但是由于它更親近于數(shù)據(jù)持久的二維表,沒有像領(lǐng)域模型那樣需要復(fù)雜的ORM支持。書對于數(shù)據(jù)驅(qū)動的應(yīng)用或模塊非常適合。POEAA中也已經(jīng)給出了這種bizLogic最有效的持久層實現(xiàn),就是table getway,當(dāng)然也可以使用其他的方式比如“查詢工廠”。
事實上,最多使用這種模式的情況是當(dāng)后臺數(shù)據(jù)源大部分都是一種兩維甚至多維數(shù)據(jù)結(jié)構(gòu)的時候進行。比如一個極端的例子(幾乎沒有業(yè)務(wù)),一個應(yīng)用的復(fù)雜查詢模塊,這種模塊就是一個查詢模型加上一組對數(shù)據(jù)進行排列統(tǒng)計過濾的TableModule。
表模塊還具有很多特點:處理的二維數(shù)據(jù)表將成為代碼的核心部分。所以,是否使用tableModule還會取決于整個應(yīng)用的其他部分是否對這種二維表提供強大的支持。(如上圖)
優(yōu)點:持久層架構(gòu)簡單,在復(fù)雜度大的以數(shù)據(jù)為核心的應(yīng)用中開發(fā)效率極高。而且表模塊能夠識別的table越多,能夠處理table的組建工具越強,這種模型的能力越強。
缺點:不能適應(yīng)復(fù)雜的應(yīng)用邏輯,或者與表結(jié)構(gòu)差別較大的應(yīng)用邏輯。由于沒有對內(nèi)部的兩位數(shù)據(jù)表(table)進行有效標識的方式(比如,無法快速簡單的確定使用table是否是需要的數(shù)據(jù)內(nèi)容),對于大量細顆粒的邏輯會增加其復(fù)雜度。
其實java中的 rowset/jdbc resultset,.net中的
dateSet/dataTable都屬于表模塊操作的二維表。但是,由于.net在GUI層面以及持久化層面對他自己的”二維表”的強大支持使得 TableModule幾乎成為MS.Net上的首選模式。這也就可以解釋了,許多.net開發(fā)人員一直抱怨,看到dataset/dataTable泛濫,甚至在WebService中也是這樣。而java中卻有所不同,雖然有持久化用到的jdbc/resultSet的支持(事實上jdbc/ado 給出的接口都只直接適合TableModule。),然而其他方面就少得可憐了。所以,使用java還是以其他的bizLogic架構(gòu)模式為好。除非你的邏輯真的很簡單,簡單到把resultSet放在jsp中都不會造成邏輯混亂。又或者你能夠自己提供一套完整的 rowset組建框架。