ORM(Object Relational Mapping)技術(shù)為什么是有效的?對(duì)這個(gè)問題一般的答案是ORM解決了面向?qū)ο蠹夹g(shù)和關(guān)系數(shù)據(jù)庫之間的阻抗匹配問題。但是任何一種成功的技術(shù),它的支持理由都不會(huì)是單一的。在Witrix平臺(tái)的實(shí)踐中,ORM的如下幾個(gè)特性是關(guān)鍵性的:
1. 主鍵和對(duì)象之間的一一對(duì)應(yīng)關(guān)系。在Web應(yīng)用中,前臺(tái)瀏覽器持有的只能是對(duì)象的某種表示, 因此一種locator機(jī)制是最基礎(chǔ)的要求。
2. Container結(jié)構(gòu)。Container所擁有的信息包括其所有元素以及元素之間的關(guān)系。因?yàn)镃ontainer具有全局知識(shí),所以它可以解決對(duì)象圖中的循環(huán)依賴問題。正是因?yàn)閟ession中一級(jí)緩存的存在,才能在實(shí)體延遲加載的情況下保證對(duì)象引用的唯一性,保證a.b.c.a == a。在程序設(shè)計(jì)中,所有支持對(duì)象圖的Container結(jié)構(gòu)都是non-trivial的,都必然是有價(jià)值的。例如spring容器在配置管理方面最重要的價(jià)值就在于可以管理循環(huán)依賴的對(duì)象創(chuàng)建過程。而在witrix平臺(tái)的前臺(tái)所定義的ControlManager管理器其核心作用就在于協(xié)調(diào)前臺(tái)控件之間的消息響應(yīng)依賴關(guān)系。從spring的配置文件可以清楚的看出,bean的聲明過程是順序進(jìn)行的,但是bean的創(chuàng)建過程是非順序結(jié)構(gòu)的。在數(shù)學(xué)上,我們說系統(tǒng)的拓?fù)?topology)發(fā)生了變化。
A a = new A(); B b = new B(); a.setB(b); b.setA(a);
3. 對(duì)象作為復(fù)雜屬性的集合。關(guān)系數(shù)據(jù)庫中保存的都是原子性數(shù)據(jù),每一列都是不可再分解的原始數(shù)據(jù)類型,數(shù)學(xué)上稱之為標(biāo)量(scalar). 而ORM引擎返回的直接就是嵌套的復(fù)雜數(shù)據(jù)類型,因此不再需要一個(gè)額外的造型過程.雖然總是返回全部數(shù)據(jù)列不是很優(yōu)化,但是這種強(qiáng)制性的較粗的處理粒度使得前臺(tái)程序可以有更多的選擇自由.
4. 對(duì)兩兩關(guān)系的內(nèi)蘊(yùn)表達(dá)及充分利用.關(guān)系數(shù)據(jù)庫中所保存的是系統(tǒng)分解后的表示,即關(guān)系被分解了而不是被表達(dá)了,外鍵對(duì)數(shù)據(jù)關(guān)系只起到一種約束作用,它對(duì)于查詢語句的構(gòu)建并沒有直接的影響.所有數(shù)據(jù)之間的關(guān)系都必須在查詢的時(shí)候明確指定出來,即調(diào)用者必須擁有數(shù)據(jù)關(guān)系的知識(shí),而不是數(shù)據(jù)本身擁有這些知識(shí).在如下的sql語句中
select * from a, b
where a.fldA = b.fldB
and a.fldC = 1 and b.fldD = 2
a.fldA = b.fldB 可以稱為關(guān)聯(lián)條件,而a.fldC=1可以稱作是坐標(biāo)條件.SQL的復(fù)雜性很大程度上來源于我們頻繁的需要在各處指定完全一樣的關(guān)聯(lián)條件而無法把它們抽象成可復(fù)用的組分.在ORM所提供的對(duì)象空間中,對(duì)象之間的兩兩關(guān)聯(lián)只要指定一次,就可以在增刪改查等各種操作過程中起到作用,特別是在對(duì)象查詢語句中,可以通過兩兩關(guān)聯(lián)自動(dòng)推導(dǎo)出多實(shí)體之間的關(guān)聯(lián)關(guān)系,雖然推導(dǎo)出的結(jié)果未必是最優(yōu)化的.
select from a where a.fldC = 1 and a.b.fldD = 2
在Witrix平臺(tái)中,我們做了大量的工作以確保對(duì)象上的復(fù)合屬性(例如a.b.fldD)和本征屬性(例如a.fldC)在使用上是完全等價(jià)的.這些工作的結(jié)果并不僅僅是減少了一些應(yīng)用層的代碼量,它使得系統(tǒng)結(jié)構(gòu)發(fā)生了深刻的變化.復(fù)合屬性把單表模型推進(jìn)到了業(yè)務(wù)主題模型,使得單一業(yè)務(wù)對(duì)象可以聚集某一范圍內(nèi)的相關(guān)結(jié)構(gòu)信息,這才使得witrix的模型分解技術(shù)成為可能。因此在我們看來,HQL是hibernate價(jià)值的集中體現(xiàn).
5. POJO提供了純粹的first class的持久化結(jié)構(gòu)空間.采用POJO結(jié)構(gòu)可以充分利用現(xiàn)有語言及開發(fā)工具中的一系列基礎(chǔ)設(shè)施,大大降低了持久化結(jié)構(gòu)的構(gòu)造成本.而透明的get/set操作使得我們可以完全基于相對(duì)知識(shí)對(duì)持久化結(jié)構(gòu)進(jìn)行變換,在完全不依賴外部環(huán)境信息(例如數(shù)據(jù)庫連接和ResultSet界面)的情況下解決系統(tǒng)的主要業(yè)務(wù)結(jié)構(gòu)問題.這一切成為可能在技術(shù)上都源于AOP(Aspect Oriented Programming)所引入的重新詮釋的能力,它使得我們可以將對(duì)象上的某種相對(duì)操作重新詮釋為對(duì)數(shù)據(jù)庫的相應(yīng)操作.
http://canonical.javaeye.com/blog/37064 6. Entity具有活動(dòng)能力.Entity并不是完全被動(dòng)的數(shù)據(jù)容器,而是可以定義復(fù)雜動(dòng)作的對(duì)象.在Witrix平臺(tái)中,后臺(tái)程序大致具有如下結(jié)構(gòu)
Entity ---- 結(jié)構(gòu)問題
Handler ---- 業(yè)務(wù)動(dòng)作定義
BizFlow ---- 動(dòng)力學(xué)問題
Handler類似于J2EE中傳統(tǒng)的Service層,只是一般實(shí)現(xiàn)的方法要少的多.而BizFlow是某種結(jié)合了界面表示的流程引擎.基于實(shí)體結(jié)構(gòu)使得系統(tǒng)在細(xì)粒度處具有某種活動(dòng)能力,便于我們構(gòu)造一些局部結(jié)構(gòu)來解決問題,因而也就緩解了大量操作在Service層的堆積過程,有利于維護(hù)系統(tǒng)整體結(jié)構(gòu)的對(duì)稱性.
----------- ==> -------------|--
----------- |--
通過對(duì)于ORM技術(shù)的理論分析,Witrix平臺(tái)采取了一些和一般J2EE架構(gòu)不同的設(shè)計(jì).實(shí)際上目前J2EE架構(gòu)下的常見的DAO模式在使用ORM技術(shù)的情況下往往不是合適的選擇,因?yàn)镈AO的一般設(shè)計(jì)是封裝某個(gè)實(shí)體相關(guān)的操作,它直接破壞了ORM的container結(jié)構(gòu)。原先我們只需要EntityManager.get(entityClass, id)這一通用方法既可得到各種數(shù)據(jù)實(shí)體對(duì)象,而現(xiàn)在需要對(duì)每種實(shí)體調(diào)用不同的Dao函數(shù),顯然這是對(duì)系統(tǒng)結(jié)構(gòu)的重大破壞。在Witrix平臺(tái)的設(shè)計(jì)中沒有獨(dú)立的DAO層,它通過通用的EntityDao統(tǒng)一完成所有對(duì)象的存取過程,而不是每個(gè)XXXManager繼承公共的Dao類。即整個(gè)系統(tǒng)架構(gòu)中盡量維護(hù)數(shù)據(jù)存取過程的統(tǒng)一性而不是實(shí)現(xiàn)它的分散化。
在Witrix平臺(tái)的Workflow引擎,Wiki引擎等模塊的設(shè)計(jì)中,IWorkflowStore和IWikiStore等類的設(shè)計(jì)類似于DAO模式,是對(duì)存取方式的一種封裝。在比較復(fù)雜的模塊中,對(duì)于存取邏輯做出一定的封裝是需要的。但是注意到Store類的設(shè)計(jì)和實(shí)體框架的設(shè)計(jì)相比,其結(jié)構(gòu)可分解性要相差很多,它基本上只提供對(duì)外的服務(wù)接口。如果我們能夠?qū)τ谖募到y(tǒng)等存儲(chǔ)設(shè)施作出充分多的工作,我們一樣可以對(duì)于非關(guān)系數(shù)據(jù)庫的某些存取形式完成Container結(jié)構(gòu),只是這個(gè)工作量過大,而我們一般并不需要對(duì)非通用的存取結(jié)構(gòu)掌握如此充分的知識(shí)。
實(shí)體結(jié)構(gòu)隱含的擴(kuò)展了系統(tǒng)的同時(shí)性視圖,a.b.c.a == a 所隱含表達(dá)的事實(shí)是a,b,c是同時(shí)存在的.
http://canonical.javaeye.com/blog/33797 在某些時(shí)候,例如當(dāng)我們需要將系統(tǒng)結(jié)構(gòu)順序化,序列化的時(shí)候,這種同時(shí)性會(huì)成為一種障礙.因此Witrix平臺(tái)中數(shù)據(jù)同步所使用的ETL(Extract Transform Load)引擎是基于表結(jié)構(gòu)(分解后信息)的,而不是基于實(shí)體結(jié)構(gòu)(關(guān)聯(lián)信息)的.實(shí)際上,關(guān)系模型在某種意義上是系統(tǒng)分解后的必然結(jié)果,因此隨著我們對(duì)系統(tǒng)的理解的粒度要求越來越精細(xì),很可能最終需要我們明確意識(shí)到關(guān)系對(duì)象本身的存在性,最終實(shí)體模型會(huì)非常近似于關(guān)系模型.只不過在實(shí)體模型級(jí)列中我們選擇的余地更大,關(guān)系模型可以看作是它的某種極限.理想的情況是在不同的時(shí)刻我們可以使用不同的關(guān)系抽象,只是受限于目前的實(shí)現(xiàn)技術(shù),在系統(tǒng)構(gòu)建時(shí)刻基礎(chǔ)的關(guān)系結(jié)構(gòu)往往就被固化下來.