JDO之前世今生 |
(本文轉(zhuǎn)自《CSDN開發(fā)高手》2003第10期)
1 Java與數(shù)據(jù)庫應(yīng)用,JDBC Java發(fā)明以來,在短短的幾年之間,迅速占領(lǐng)了從桌面應(yīng)用(J2SE)到服務(wù)器(J2EE),再到小型設(shè)備嵌入式系統(tǒng)(J2ME)的應(yīng)用開發(fā)市場,其語言吸取了SmallTalk的一切皆對象的理念,擺脫了C++的歷史累贅,簡潔、自由的風(fēng)格贏得了很多開發(fā)者的喜愛。從JDK1.1開始,Java成為實用的語言,而不是被人觀望的新品秀;再經(jīng)過JDK1.2的大量增強(尤其是Collection Framework),JDK1.3的虛擬機效率提升(HotSpot),JDK1.4的融合百家之長(Logging、RegExp、NewIO等),現(xiàn)在已經(jīng)是成熟穩(wěn)重,頗顯大家風(fēng)范。 在企業(yè)級市場上,大部分的應(yīng)用建立在數(shù)據(jù)庫基礎(chǔ)上,數(shù)據(jù)是企業(yè)的生命,傳統(tǒng)開發(fā)語言,包括面向過程的C、面向?qū)ο蟮腃++、變種Pascal的Delphi(非常棒的語言,我用過四年),面向數(shù)據(jù)的PowerBuilder等等,先后在數(shù)據(jù)庫開發(fā)的舞臺上展現(xiàn)風(fēng)姿。Java當(dāng)然不會放過這些,于是,出現(xiàn)了JDBC。在JDBC的幫助下,Java也迅速滲入數(shù)據(jù)庫開發(fā)的市場,尤其是面向企業(yè)服務(wù)器的應(yīng)用開發(fā)。 今天要談的JDO,與JDBC有非常密切的關(guān)系,盡管JDO并不是只面向JDBC的數(shù)據(jù)對象包裝規(guī)范。下面先簡單地介紹一下JDBC。
1.1 關(guān)系數(shù)據(jù)庫之百家爭鳴,ODBC關(guān)系數(shù)據(jù)庫的歷史一言難盡,我只能從我的接觸經(jīng)歷和所見所聞,簡單地敘述一下。最早的時候,計算機還只在一些大型的研究機關(guān)露面,并不是普羅大眾可以涉及的。蘋果電腦將個人電腦引入民間,再隨著IBM的PC標(biāo)準(zhǔn)開放,個人電腦逐步普及開來,加上微軟的DOS操作系統(tǒng),以及Borland的Turbo系列語言開發(fā)環(huán)境,老百姓發(fā)現(xiàn)原來電腦可以做這么多事!后來,出現(xiàn)了DBASE,一個簡單的關(guān)系數(shù)據(jù)庫系統(tǒng),和SQL語言。后來,Borland看到了數(shù)據(jù)庫的市場前景,推出了Paradox(也是當(dāng)今Delphi和C++Builder中仍然使用的Paradox),一舉占領(lǐng)了民用數(shù)據(jù)庫的大部分江山,之后,Borland干脆收購了Dbase,后來又購買了InterBase,將數(shù)據(jù)庫市場的領(lǐng)先優(yōu)勢一直保持到Windows3.0出現(xiàn)。這時候,微軟在Windows1.0和2.0被人痛罵之后頑強地推出3.0,以及更穩(wěn)定的3.1和Win32API,造就了個人電腦桌面操作系統(tǒng)的霸主地位,在Borland未警覺的情況下,購買了同樣具有類Dbase數(shù)據(jù)庫技術(shù)的Fox公司,并迅速將其易用化,形成了FoxBase,后來演變成FoxPro,逐漸超過了Borland,成為個人電腦數(shù)據(jù)庫的大戶。微軟再接再勵,為簡單易用而低負(fù)荷要求的數(shù)據(jù)庫應(yīng)用開發(fā)了Access,贏得了廣大開發(fā)人員的心。當(dāng)然,同期的Oracle、Sybase、Informix等商用數(shù)據(jù)庫憑專注于企業(yè)級數(shù)據(jù)庫技術(shù)成為高端的幾位領(lǐng)軍人物。微軟當(dāng)然也想成為高端數(shù)據(jù)庫供應(yīng)商之一,于是自行開發(fā)一套面向企業(yè)級應(yīng)用的數(shù)據(jù)庫,不過很快項目夭折,微軟不甘心,購買了Sybase的底層TDS技術(shù),包裝成了SQL Server,憑微軟的高度易用性的特點,也占領(lǐng)了不少市場。 當(dāng)市場上出現(xiàn)眾多的數(shù)據(jù)庫產(chǎn)品之后,Borland和微軟都發(fā)現(xiàn)自己擁有的數(shù)據(jù)庫產(chǎn)品挺多,市場也不小,不同的產(chǎn)品給用戶帶來不同的配置任務(wù),不利于所有產(chǎn)品的推廣,于是,兩者紛紛開始制定數(shù)據(jù)庫訪問的規(guī)范,微軟推出了ODBC,其面向開發(fā)人員的親和性,逐步獲得了認(rèn)可,同時,Borland糾集了IBM和Novell也推出了IDAPI數(shù)據(jù)庫接口規(guī)范,也就是今天BDE的核心,不過后來Novell和IBM先后退出,只剩Borland獨力支撐。不過Borland是一個技術(shù)實力雄厚的公司,其技術(shù)一向領(lǐng)先于微軟,BDE的性能比初期的ODBC不知道要好多少倍,后來微軟偷師學(xué)藝,把連接池等技術(shù)加到ODBC中,在Delphi3.0及其BDE在市場上風(fēng)光無限的時候,逐步趕了上來并有超過。直到今天,BDE仍是Borland的產(chǎn)品線上的數(shù)據(jù)庫訪問標(biāo)準(zhǔn),而微軟如果不是將ODBC和多數(shù)數(shù)據(jù)庫的客戶端內(nèi)嵌進(jìn)Windows的話,估計BDE仍是市場的贏家。不過,微軟是玩弄市場的老手,通過對操作系統(tǒng)的壟斷,其數(shù)據(jù)庫產(chǎn)品和ODBC標(biāo)準(zhǔn)終究占據(jù)了多數(shù)開發(fā)市場。
1.2 從optional pack到JDK的標(biāo)準(zhǔn)API Java開始涉及數(shù)據(jù)庫應(yīng)用后,Sun就極力制定Java的數(shù)據(jù)庫規(guī)范,JDBC API就是類似ODBC一樣,對數(shù)據(jù)庫訪問的底層協(xié)議進(jìn)行最基本的包裝,然后形成一套統(tǒng)一的數(shù)據(jù)訪問接口,數(shù)據(jù)庫連接、SQL語句句柄、結(jié)果集,都帶有ODBC的影子。以方便配置為目的,Sun極力推薦完全瘦客戶端的TYPE 4型JDBC驅(qū)動,這是一個不需要安裝數(shù)據(jù)庫客戶端的驅(qū)動規(guī)范,是現(xiàn)在使用最多的。當(dāng)然,為了保持與舊的數(shù)據(jù)庫兼容,JDBC規(guī)范中包括了專用于連接ODBC的TYPE 1驅(qū)動和需要安裝數(shù)據(jù)庫客戶端的TYPE 2驅(qū)動,以及可以由廠商在數(shù)據(jù)庫服務(wù)端專門提供面向JDBC的服務(wù)的TYPE 3驅(qū)動。 JDBC最早出現(xiàn)時,還不屬于標(biāo)準(zhǔn)JDK的一部分,而是作為一個額外包提供下載。后來,隨著Java編寫的數(shù)據(jù)庫應(yīng)用的的增多,和JDBC規(guī)范本身的逐漸成熟,JDBC終于成為JDK1.1的一部分。 JDBC目前最新的是3.0版本,還有正在討論中的4.0版本。實際上,在開發(fā)中使用得最多的還是1.0中的API,2.0中主要增加了可雙向滾動的結(jié)果集、更新批處理等提高可用性和性能的API,3.0主要增加了連接池、可更新的結(jié)果集等特性。4.0將在可管理性、連接池規(guī)范化等方面再做改進(jìn)。
2 面向?qū)ο笈c數(shù)據(jù)庫 現(xiàn)在的程序員,沒有不知道面向?qū)ο蟮摹W鳛榻咏鎸嵖陀^世界的開發(fā)概念,面向?qū)ο笫钩绦虼a更易讀、設(shè)計更合理。在普遍存在的數(shù)據(jù)庫應(yīng)用領(lǐng)域,開發(fā)人員對面向?qū)ο蟮淖非髲奈赐V惯^。從八十年代開始,就有很多公司和研究機構(gòu)在進(jìn)行著面向?qū)ο笈c數(shù)據(jù)庫結(jié)合的研究。
2.1 SmallTalk、C與C++、Delphi—Object Pascal、Java面向?qū)ο蟮恼Z言最早有好幾種雛形,IBM的SmallTalk是其中最為流行的,在SmallTalk中,一切都是對象,一切都是類,它將面向?qū)ο蟮母拍畎l(fā)揮到了極致。面向?qū)ο蟮木幊瘫绕饌鹘y(tǒng)的面向過程的方式挺進(jìn)了一大步,使人們認(rèn)識到:原來軟件可以這樣寫。不過,由于計算機基本結(jié)構(gòu)與底層硬件體系和系統(tǒng)軟件的限制,SmallTalk還不能在理想的性能前提下推廣到普通的應(yīng)用上,這一點暫時限制了SmallTalk的發(fā)展,接著,C語言的面向?qū)ο蟀鍯++出現(xiàn)了,由于使用C語言的人很多,C++很快成為面向?qū)ο缶幊痰闹髁髡Z言。不過,為了保證與C的兼容,C++保留了很多面向過程的痕跡,比如惡心的指針、全局變量等等。Pascal的改進(jìn)版Object Pascal相對來說安全許多,后來Borland干脆將Object Pascal換了個名字,叫Delphi,從此開創(chuàng)了一片面向?qū)ο缶幊痰男率澜纾?nbsp;Delphi的嚴(yán)謹(jǐn)語法和快速編譯吸引了眾多的應(yīng)用開發(fā)者,加上Borland的完美的VCL組件體系,比起MFC來方便而容易,另外,Delphi完整的數(shù)據(jù)庫組件,也將數(shù)據(jù)庫開發(fā)變得簡單而容易,Delphi再次成為成熟的面向?qū)ο箝_發(fā)語言。微軟當(dāng)然不會放過這些,通過將MFC內(nèi)置到操作系統(tǒng)中,微軟的VC++也搶回一些市場。這也是為什么Delphi開發(fā)的應(yīng)用程序編譯后會比VC、VB開發(fā)的程序大的原因。 1995年,Sun的一個開發(fā)小組本來為了小型嵌入式系統(tǒng)開發(fā)OAK語言,結(jié)果無心插柳柳成蔭,發(fā)展出了Java語言,它是一個完全擺脫了傳統(tǒng)語言的各種負(fù)擔(dān)的面向?qū)ο蟮恼Z言,當(dāng)然,也保留了一些非面向?qū)ο蟮暮诵模ㄔ碱愋停┮员WC速度。現(xiàn)在Java也為最流行的面向?qū)ο笳Z言之一。當(dāng)然,微軟同樣不會放過它,擅于模仿的微軟立即弄出一個C#來與之競爭,并在C#中保留了一些變種的指針(指代)以吸引傳統(tǒng)的C開發(fā)者。關(guān)于這些語言的各自特點,這里就不一一贅述了。
2.2 數(shù)據(jù)庫與數(shù)據(jù)對象化 數(shù)據(jù)庫是企業(yè)級應(yīng)用不可缺少的,因此,在面向?qū)ο罅餍械臅r候,數(shù)據(jù)庫廠商也在進(jìn)行著數(shù)據(jù)對象化的研究。這些研究在上個世紀(jì)八十年代就初現(xiàn)端倪。 數(shù)據(jù)庫的對象化一般有兩個方向:一個是在主流的關(guān)系數(shù)據(jù)庫的基礎(chǔ)上加入對象化特征,使之提供面向?qū)ο蟮姆?wù),但訪問語言還是基于SQL;另一個方向就是徹底拋棄關(guān)系數(shù)據(jù)庫,用全新的面向?qū)ο蟮母拍顏碓O(shè)計數(shù)據(jù)庫,這就是對象數(shù)據(jù)庫ODBMS。
2.2.1 關(guān)系數(shù)據(jù)庫對象化、SQL99與JDBC3.0隨著許多關(guān)系數(shù)據(jù)庫廠商開始提供對象化服務(wù),各自的接口開始互不兼容,在經(jīng)歷一些麻煩之后,關(guān)系數(shù)據(jù)庫廠商感覺到規(guī)范化的必要,因為當(dāng)初關(guān)系數(shù)據(jù)庫雄霸天下時SQL92標(biāo)準(zhǔn)起了很大作用,大家可以按照統(tǒng)一的編程方式來訪問高性能的商用數(shù)據(jù)庫。 關(guān)系數(shù)據(jù)庫廠商集中起來,重新將對象化服務(wù)規(guī)范起來,形成了SQL99規(guī)范,將其中的對象結(jié)構(gòu)等內(nèi)容規(guī)范起來,開始一個嶄新的面向?qū)ο蟮年P(guān)系數(shù)據(jù)庫(ORDBMS)的歷程。 JDBC3.0就是在這種情況下出臺的,它將對關(guān)系數(shù)據(jù)庫中的對象服務(wù)的訪問API規(guī)范起來,為Java平臺提供了訪問ORDBMS的標(biāo)準(zhǔn)方式。當(dāng)然,JDBC3.0對傳統(tǒng)的SQL操作也進(jìn)行了很多功能增強。 Oracle是一個傳統(tǒng)的關(guān)系數(shù)據(jù)庫廠商,在對象化的道路上,Oracle當(dāng)然采取追加對象化特征的道路,以侵入數(shù)據(jù)對象化的市場,保持Oracle在數(shù)據(jù)庫領(lǐng)域的領(lǐng)導(dǎo)地位。如果說Oracle7.4使Oracle走向全盛的話,從Oracle8開始,Oracle就成為關(guān)系數(shù)據(jù)庫加對象類型的先驅(qū)。在Oracle8中,我們可以定義一些數(shù)據(jù)結(jié)構(gòu)(Record),將普通的類型包裝在其中成為數(shù)據(jù)元素,然后可以在客戶端按Record結(jié)構(gòu)進(jìn)行訪問,初步提供了面向?qū)ο蟮臄?shù)據(jù)庫服務(wù)。
2.2.2 對象數(shù)據(jù)庫 對象數(shù)據(jù)庫就是采用全新的面向?qū)ο蟾拍顏碓O(shè)計數(shù)據(jù)庫的全新數(shù)據(jù)庫類型。在這方面,主要以一些大學(xué)研究機構(gòu)進(jìn)行設(shè)計和開發(fā),有些也形成了產(chǎn)品,不過由于市場方面的原因(主要是關(guān)系數(shù)據(jù)庫的容易上手和市場絕對領(lǐng)導(dǎo)地位)和ODBMS先天的一些弱點(比如查詢引擎很難優(yōu)化),使ODBMS沒有象關(guān)系數(shù)據(jù)庫那樣流行起來。 不過對象數(shù)據(jù)庫的對象化特點還是令人割舍不下,目前還是有一些很好的產(chǎn)品在市場上,從商用的到免費的都用。目前在ODBMS領(lǐng)域占據(jù)領(lǐng)導(dǎo)地位的是Versant、FastObjects和ObjectStore等幾大廠商,并且,市場份額也在逐步擴展。免費的產(chǎn)品包括C++編寫的Ozone、純Java的db4o等等。還有一些研究機構(gòu)開發(fā)一些底層的面向?qū)ο髷?shù)據(jù)庫引擎,但只提供一些底層的API,不提供管理方面的功能,以及一些算法提供開放式接口,讓廠商去選擇和實現(xiàn)。比如美國威斯康新大學(xué)計算機系數(shù)據(jù)庫組的SHORE引擎,就是一個非常出色的面向?qū)ο髷?shù)據(jù)庫引擎,現(xiàn)在還在積極的更新中,一些其它研究機構(gòu)和數(shù)據(jù)庫廠商采用它完成了自己的特別的對象數(shù)據(jù)庫,比如專用于地理信息的數(shù)據(jù)庫、專用于宇宙空間數(shù)據(jù)研究的數(shù)據(jù)庫等等。 目前對象數(shù)據(jù)庫最大的障礙是缺乏統(tǒng)一的規(guī)范,各個數(shù)據(jù)庫廠商有各自的訪問接口。對象數(shù)據(jù)庫比起關(guān)系數(shù)據(jù)庫來,不只是基本的幾種數(shù)據(jù)類型那么簡單,它還涉及繼承處理、多態(tài)等一大堆面向?qū)ο筇卣鞯膶崿F(xiàn),規(guī)范化道路當(dāng)然困難重重。這也是對象數(shù)據(jù)庫無法普及的一個重要原因。 也有一些機構(gòu)提出了一些建議的規(guī)范,比如制定Corba標(biāo)準(zhǔn)的OMG小組的一個分組ODMG提出的ODMG規(guī)范,目前已經(jīng)是3.0版本,其中的OQL對象查詢語言相當(dāng)具有吸引力。還有一些中立的機構(gòu)提出了其它的一些標(biāo)準(zhǔn)化的對象訪問API,也可算是面向?qū)ο髷?shù)據(jù)庫的規(guī)范之一。象前面提到的FastObjects和Ozone就是符合ODMG3.0規(guī)范的。
3 Java對象映射 話說回來,在一般的開發(fā)人員眼中,數(shù)據(jù)庫就是指關(guān)系數(shù)據(jù)庫,因此,很多應(yīng)用還是采用簡單的JDBC來訪問數(shù)據(jù)庫。在開發(fā)的過程中,大家逐漸感覺到JDBC的局限性,比如調(diào)用復(fù)雜、容易產(chǎn)生資源泄漏等等,與面向?qū)ο蟮腏ava語言有一段距離,因此,很多開發(fā)小組開始思考如何將應(yīng)用中的數(shù)據(jù)進(jìn)行對象化建模,然后再想辦法與JDBC結(jié)合起來,這就是Java數(shù)據(jù)庫開發(fā)中的層出不窮的對象包裝技術(shù)。
3.1 對象包裝技術(shù)
3.1.1 傳統(tǒng)包裝與演變 傳統(tǒng)包裝顧名思義,就是最初出現(xiàn)的包裝方式,很多公司都經(jīng)歷過這一步,產(chǎn)生了很多風(fēng)格各異的包裝方法。當(dāng)然,筆者也有過還算豐富的嘗試過程。 舉例來說,如果我們有一個用戶類: public class User { public int userId; public String name; public java.util.Date birthday; } 我們可以將其當(dāng)作一個簡單的數(shù)據(jù)類,然后寫一些工具方法來實現(xiàn)與JDBC的交互。這些方法,我們可以放到一個另外的工具類中,也可以放到User類中作為靜態(tài)方法。這些方法包括簡單的增、刪、改、查(以O(shè)racle為例): public class User { public int userId; public String name; public java.util.Date birthday;
public static User addUser(String name, Date birthday) throws SQLException { Connection conn = …; //獲取一個JDBC連接 PreparedStatement ps = conn.prepareStatement(“…”); // 獲取一個序列值來作為用戶標(biāo)識 ResultSet rs = ps.executeQuery(); rs.next(); User user = new User(); user.userId = rs.getInt(1); //讀取序列值為新用戶標(biāo)識 user.name = name; user.birthday = birthday; ps = conn.prepareStatement(“insert into ….”); //插入用戶數(shù)據(jù)記錄的SQL ps.setInt(1,user.id); ps.setString(2,user.name); ps.setDate(3,user.birthday); ps.executeUpdate(); rs.close(); ps.close(); conn.close(); return user; }
public static void deleteUser(int userId) throws SQLException { Connection conn = ….; //… }
public static User getById(int userId) throws SQLException { //… }
//… }
以上就是一個簡單的數(shù)據(jù)包裝的基本雛形,我們可以看到,這是一個非常簡單的JDBC包裝,一些代碼可以模塊化,以實現(xiàn)重用。另外,這段代碼還有很大隱患,就是中途如果出現(xiàn)異常的話,就會使系統(tǒng)出現(xiàn)JDBC資源漏洞,因為JDBC分配的資源(conn,ps,rs等)是不能被Java虛擬機的垃圾回收機制回收的。因此,我們的addUser方法就需要改成下面的樣子: public static User addUser(String name, Date birthday) throws SQLException { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; User user = new User(); try { conn = …; //獲取一個JDBC連接 ps = conn.prepareStatement(“…”); // 獲取一個序列值來作為用戶標(biāo)識 rs = ps.executeQuery(); rs.next(); user.userId = rs.getInt(1); //讀取序列值為新用戶標(biāo)識 user.name = name; user.birthday = birthday; ps = conn.prepareStatement(“insert into ….”); //插入用戶數(shù)據(jù)記錄的SQL ps.setInt(1,user.id); ps.setString(2,user.name); ps.setDate(3,user.birthday); ps.executeUpdate(); } finally { //這里注意一定要按照創(chuàng)建的順序關(guān)閉JDBC資源: if(rs != null) try { rs.close(); } catch(SQLException ex) { ex.printStackTrace(); } if(ps != null) try { ps.close(); } catch(SQLException ex) { ex.printStackTrace(); } if(conn != null) try { conn.close(); } catch(SQLException ex) { ex.printStackTrace(); } } return user; }
所有的數(shù)據(jù)庫訪問方法都必須進(jìn)行這樣的包裝,當(dāng)我們的數(shù)據(jù)類達(dá)到一定的數(shù)量后(比如十幾個,幾十個),這些方法占據(jù)了大量的代碼,維護(hù)困難、出現(xiàn)BUG機會增多,并且不易排錯,尤其是資源漏洞這種容易引起服務(wù)器穩(wěn)定性問題的BUG。 為了保持?jǐn)?shù)據(jù)類的純潔,我們可以將JDBC操作方法集中到一個公共工具類中去完成,這樣,這個工具類會非常龐大,但每個數(shù)據(jù)類會變得很簡單,這種方式,可以稱作是DataAccessObject模式,相當(dāng)于EJB中的ValueObject,是脫離數(shù)據(jù)庫細(xì)節(jié)的純對象模型。 這些都是最基本的存儲處理,在基本增刪改查(這里的查指按關(guān)鍵字查找對象)的基礎(chǔ)上,我們還需要進(jìn)行復(fù)雜的匹配查詢(SQL),這使得我們的存儲處理代碼進(jìn)一步復(fù)雜化。簡單地,我們可以寫一個類似的方法: public static Collection findBy(String sql) throws SQLException { //… (這里獲取JDBC連接) Collection col = new Vector(); ps = conn.prepareStatement(sql); rs = ps.executeQuery(); while(rs.next()) { User user = new User(); user.userId = rs.getInt(1); user.name = rs.getString(2); user.birthday = rs.getDate(3); col.add(user); } return col; //… (同前,這里是清理JDBC資源的代碼) } 這就是一個查詢接口的基本定義,查詢采用的語言仍是SQL。 如果我們需要將參數(shù)從SQL串中獨立出來以節(jié)省數(shù)據(jù)庫的解析時間并規(guī)范化,我們還需要將查詢條件作為參數(shù)傳遞到這個方法中去,方法的接口改為: public static Collection findBy(String sql, Object[] params) throws SQLException { //… ps = conn.prepareStatement(sql); for(int i = 0; i < params.length; i++) ps.setObject(i+1,params[i]); //… } 調(diào)用的時候sql參數(shù)中會包含一些“?”號,如: select ID,NAME,BIRTHDAY from USER where … = ? and … > ? and … 當(dāng)然,也有一些開發(fā)團隊喜歡將所有可能的查詢都寫死成一個個的專用查詢方法,在其中完成對應(yīng)的SQL操作,這一點類似于EJBQL,只不過是將EJBQL中容器實現(xiàn)的功能通過手工編碼來實現(xiàn)。這樣做使得查詢受到限制,但可以提供更保險的接口。 還有一些開發(fā)人員看到每個類中寫這樣一些查詢方法使得這個類的代碼變得龐大,維護(hù)麻煩,便將所有的查詢方法放到一個公共的工具類中去,只是在方法中再加入一個參數(shù):Class cls來表示需要查詢哪個對象,使得每個數(shù)據(jù)類變得緊湊一些。當(dāng)然,這樣的結(jié)果是那個公共類變得異常龐大,誰維護(hù)誰倒霉,可以說是犧牲一人,幸福團隊。不過如果這個人心理素質(zhì)不夠好、壓力承受能力不強的話,一些對數(shù)據(jù)類的改動可能會受到他的阻礙,這時候就是“一夫當(dāng)關(guān),萬夫莫開”。
現(xiàn)在,我們已經(jīng)實現(xiàn)了基本對象的包裝,現(xiàn)在才能開始考慮更多的問題。首先,我們可能會從規(guī)范化的角度出發(fā),給每一個屬性加上讀寫訪問器getter/setter,在前面的User類中,可能我們會將基本屬性部分寫為: public class User { private int userId; private String name; private Date birthday;
//以下是針對以上屬性的getter/setter,一般可以用IDE工具生成 public int getUserId() { return userId; } public void setUserId(int value) { userId = value; } public String getName() { return name; } public void setName(String value) { name = value; } public Date getBirthday() { return birthday; } public void setBirthday(Date value) { birthday = value};
//… }
這樣,一個比較規(guī)范的數(shù)據(jù)類包裝就算完成了。 另外,我們知道,面向?qū)ο蟾拍钪校粋€屬性可以是另一個對象,也就是說,對象之間是存在著引用關(guān)系的,這種關(guān)系還分為一對一、一對多、多對多等幾種情況。從一個既定對象出發(fā),其某個屬性可以是另一個對象,也可以是包含另一組對象的集合。那么,在我們的數(shù)據(jù)包裝里面,當(dāng)然最好也能方便地處理對象之間的關(guān)系。假定現(xiàn)在我們又有一個數(shù)據(jù)類Group: public class Group { public int grouId; public String groupName; public Set users; //set of User } 這里為了簡單表明含義,暫不采用getter/setter。 而User對所屬的Group有一個引用: public Group belongTo; 在這里,User.belongTo和Group.users就是一個一對多的關(guān)系。 在我們的數(shù)據(jù)類中,如何才能實現(xiàn)數(shù)據(jù)庫的存取呢?就算是不考慮Group.users這個反向關(guān)系,光是User.belongTo就是一件頭疼的事。如果我們在取出一個User對象時同時將其Group對象也取出來,可以保證不會在訪問某個用戶的組時得到一個null。不過這樣有幾個缺點: 1. 數(shù)據(jù)類的存取處理(JDBC)變得復(fù)雜,需要執(zhí)行很多SQL讀取才行,有時候只需要訪問User的基本屬性時浪費時間和資源;尤其是對集合型屬性的預(yù)讀取,更加可怕 2. 如果按這個邏輯,雙向的關(guān)系處理變得危險,很容易陷入死循環(huán),如果要避免,必須在類代碼中加入一些特別的機制,也是很麻煩的事 3. 如果對象之間的關(guān)系是更復(fù)雜的情況下,比如三個、四個對象之間互相關(guān)聯(lián),那就是一場噩夢,對代碼的編寫和維護(hù)都異常艱難
于是,很多開發(fā)人員自然而然地退后一步,在User類中只保留一個groupId,并不保存Group對象,這樣,可以將User.belongTo屬性變成int類型,而另外寫一個getter方法: public Group getBelongTo() { return Group.findById(belongTo); }
而在Group類中,干脆將users屬性去掉,只保留一個方法: public Set getUsers() { return new HashSet(User.findBy(“select … from USER where BELONG_TO=?”,new Object[]{ new Integer(groupId) })); } 也許細(xì)心一點的讀者已經(jīng)看出來了,這里的幾個方法都沒有將SQLException捕捉,也沒有在方法中聲明,也就是說是有語法錯誤的,因為SQLException不是一個RuntimeException。不錯,確實是這樣,不過我們這里為了簡單明了起見,省掉這些處理,以更直接清楚地表達(dá)意思。
這樣,實際上,我們的對象關(guān)系包裝已經(jīng)名存實亡,在類的內(nèi)部有很多用于訪問所引用對象的復(fù)雜代碼,這些已經(jīng)違背了我們將對象關(guān)系保持的初衷。有些開發(fā)人員甚至不在類中保留訪問關(guān)系對象的方法,而是在客戶調(diào)用時再去訪問另一對象類的讀取方法,如: … User user = User.getById(…); //對user對象進(jìn)行一些訪問,如顯示其姓名等等 Group group = Group.findById(user.belongTo); //對group對象進(jìn)行一些訪問,如顯示組名等等 …
在這樣的代碼里,實際上我們已經(jīng)從根本上退回了關(guān)系數(shù)據(jù)庫的出發(fā)點,這與直接訪問數(shù)據(jù)表有多大區(qū)別呢?只不過是在表上面套了一層貌似面向?qū)ο蟮钠ざ选2恍业氖牵@種方式還存在于很多應(yīng)用之中。
從前面提到的這些面向?qū)ο蟀b的細(xì)節(jié)問題,我們可以看到這種傳統(tǒng)包裝方式的一些主要的缺陷:
3.1.1.1 數(shù)據(jù)庫命名與對象設(shè)計命名的一致性問題 很多時候,我們興致勃勃地設(shè)計好一個類圖,并且經(jīng)過評審之后,開始對它進(jìn)行數(shù)據(jù)庫包裝,這時候,發(fā)現(xiàn)有些屬性名在具體的數(shù)據(jù)庫中與該數(shù)據(jù)庫的關(guān)鍵字沖突,不能用作表名或字段名,必須在數(shù)據(jù)表設(shè)計時采用另外的名稱,或者很麻煩地加上引號來使用。于是,寫數(shù)據(jù)庫處理代碼的人有意見了,他必須很清楚地記得一個屬性在類中是什么屬性名,在表中又是什么字段名,在編寫的類逐漸增多后,尤其是一個類經(jīng)過歷次變動之后,或者經(jīng)過很長時間又需要改動,并去處理這些JDBC代碼時,代碼維護(hù)人員簡單要發(fā)瘋了!
3.1.1.2 對象的查詢?nèi)跃窒抻赟QL這一點也是這種簡單的包裝方法最不能擺脫關(guān)系數(shù)據(jù)庫的地方。上面也已經(jīng)說過,一些命名沖突帶來了很多維護(hù)工作量,代碼中必須還保留數(shù)據(jù)表的命名體系,而不是對象類的命名體系。這將使調(diào)用人員仍需要清楚記得兩套命名體系,無論時間經(jīng)過多久,或者開發(fā)人員是否有流動。 此外,對于普遍需要用到的連表查詢,也給應(yīng)用開發(fā)帶來困難,這些地方仍不能突破SQL的限制。
3.1.1.3 SQL資源占用多 在處理對象集合訪問或者處理集合類型屬性時,往往我們只能在同一個Connection中處理一切事務(wù),這就要求一次性地將集合中的對象全部讀入,如果集合很大的話,容易造成數(shù)據(jù)庫擁塞,使得性能大打折扣,適得其反。這方面的優(yōu)化也是很多開發(fā)人員一直在努力改進(jìn)的。
3.1.1.4 對象關(guān)系處理復(fù)雜 前面提過,對象之間的關(guān)系處理上,普通的包裝技術(shù)是一種表面上的處理,在訪問時調(diào)用者仍需要用大量的代碼進(jìn)行處理,并且,這還只是讀取,在寫入關(guān)系屬性時會有更多的細(xì)節(jié)問題需要處理。
3.1.1.5 面向?qū)ο筇厣荒軕?yīng)用一小部分 面向?qū)ο蟮陌b到前面所說的為止,都還只是很基本的處理,而面向?qū)ο蟮木A:繼承和多態(tài),在這里得不到任何幫助。我們放棄了很多合理的設(shè)計來遷就數(shù)據(jù)庫的包裝。
以上就是基本數(shù)據(jù)包裝的主要缺陷,還有更多的小問題也需要額外的處理。 不過,有責(zé)任心的開發(fā)人員當(dāng)然不會就此善罷甘休,他們冥思苦想,可能會用更好的方式來實現(xiàn)對象之間關(guān)系的處理,而且還會加入一些延遲訪問的機制,將對象之間的引用在需要用的時候才去連接數(shù)據(jù)庫取數(shù)據(jù),另外,在類的繼承上,他們也試圖去在數(shù)據(jù)庫包裝上得到體現(xiàn)。 值得感謝的是,一些富有經(jīng)驗的團隊在經(jīng)歷若干改進(jìn)之后,毫不吝惜將他們的成果貢獻(xiàn)出來,并將其獨立化,成為可復(fù)用的組件。這也就是后來出現(xiàn)的對象包裝產(chǎn)品,包括商用的和免費的。
3.1.2 產(chǎn)品化包裝中間件 面向?qū)ο蟮陌b產(chǎn)品化后,逐步推廣開來,稱作關(guān)系/對象映射:O/R Mapping。并且,在產(chǎn)品化的過程中,產(chǎn)品提供者在產(chǎn)品中逐漸提供了更多的功能。先是一些自動命名轉(zhuǎn)換器得以應(yīng)用,將客戶代碼中的類名、屬性名在內(nèi)部處理的時候自動地轉(zhuǎn)換到對應(yīng)的數(shù)據(jù)庫結(jié)構(gòu)命名空間上,這樣,應(yīng)用開發(fā)的時候不再關(guān)心具體的數(shù)據(jù)庫結(jié)構(gòu),不再需要記憶不同地命名體系,只需要一心一意地根據(jù)類圖來進(jìn)行開發(fā)。在此之后,這些O/R Mapping產(chǎn)品的開發(fā)團隊又向前邁了一大步:引入了詞法分析器,提供面向?qū)ο蟮牟樵冋Z言!很多對象關(guān)系的查詢使應(yīng)用開發(fā)變得非常方便,使O/R Mapping產(chǎn)品上了一個新的臺階。
3.1.2.1 TopLink TopLink是一個非常早期的產(chǎn)品,最初面向C++,后來也實現(xiàn)了Java的映射。TopLink性能優(yōu)異,功能強大,并且提供了獨特的查詢過濾器機制,以及對關(guān)系的處理和查詢都非常有效,于是,TopLink逐漸從商用化O/R Mapping產(chǎn)品中勝出,成為市場上的最出色的映射產(chǎn)品。也正因為這一點,最大的關(guān)系數(shù)據(jù)庫廠商Oracle將其收購,成為提供最強數(shù)據(jù)庫和最強對象映射中間件的廠商。
3.1.2.2 Castor、Hibernate TopLink雖然強大,但太強大的東西免不了得意忘形,TopLink開始將用戶鎖死到自己的產(chǎn)品上,查詢方式是最突出的。它的查詢體系含有很多別扭的概念(在我看來是如此),但為達(dá)到一般O/R產(chǎn)品不能達(dá)到的功能,開發(fā)者只能接受這些。慢慢地,也產(chǎn)生積怨,再加上其高昂的價格,讓很多新老用戶望而卻步。于是,免費的產(chǎn)品開始崛起。 免費的O/R Mapping工具有很多種,這里只提其中最有影響力的兩種:Castor和Hibernate。 Castor是Exolab組織開發(fā)的面向Java的包裝工具,它最大的特色就是實現(xiàn)了大部分的ODMG OQL規(guī)范,在查詢上,可以象完全使用一個對象數(shù)據(jù)庫一樣類圖進(jìn)行查詢(后面會有介紹)。它的原理是通過Java反射API去實現(xiàn)屬性的設(shè)置和讀取。不過由于各種原因,Castor后來的版本更新越來越慢,最終停步在1.0之前,成為至今未出到1.0正式版的O/R Mapping產(chǎn)品。不管怎么樣,它還是一個相當(dāng)不錯的產(chǎn)品。 Hibernate是一個現(xiàn)在很火熱的O/R Mapping產(chǎn)品,目前已經(jīng)出到2.0版,它功能一樣強大,同樣使用Java反射API進(jìn)行對象的設(shè)置,但它的查詢語言就是一套比較獨特的體系,這一點有點類似TopLink,但Hibernate更具有親和力,對關(guān)系的查詢更方便,只不過比起Castor來,在方便性和規(guī)范性上還是稍遜一籌。就目前狀況而言,Hibernate的用戶量和技術(shù)支持要強一些。
3.2 面向?qū)ο蟮臄?shù)據(jù)庫查詢 在對數(shù)據(jù)庫進(jìn)行面向?qū)ο笱芯康倪^程中,軟件世界的開發(fā)人員和設(shè)計人員們發(fā)現(xiàn):對數(shù)據(jù)庫能夠進(jìn)行對象化的查詢,才是對數(shù)據(jù)庫進(jìn)行徹底的面向?qū)ο蠡_@體現(xiàn)在我們使用一種全新的數(shù)據(jù)庫查詢語言,能夠很簡潔易懂地對數(shù)據(jù)庫中的對象進(jìn)行查詢。一個典型的例子如下: 假設(shè)我們已經(jīng)有前面提到的兩個數(shù)據(jù)類:User和Group,它們之間有一對多的關(guān)系:User.belongTo和Group.users。在數(shù)據(jù)庫中已經(jīng)存在很多這兩個類的實例,以及相互之間的關(guān)系。我們可以使用下面的對象式查詢語言來查詢符合條件的User對象: select * from User where User.belongTo.name=’GROUP1’ 或者 select userId,name from User where User.belongTo.name=’GROUP2’ 等等。從中我們可以看出,通過使用面向?qū)ο笾械某蓡T屬性指定符“.”,可以讓我們達(dá)到SQL中的連表的效果,實際上,第一個句查詢的SQL等價版本是: select a.* from USER a, GROUP b where a.BELONG_TO = b.GROUP_ID and b.NAME = ‘GROUP1’
由此可見,對象式的查詢語言,比起實現(xiàn)同樣功能的SQL語言來說,簡單了很多,意義也更明確,更符合使用者的思維習(xí)慣。在類圖比較復(fù)雜、查詢涉及的類又比較多的時候,這種新型的查詢語言體現(xiàn)出絕對的優(yōu)勢。
3.2.1 ODMG,OQL,Java Binding 在面向?qū)ο笫讲樵冋Z言的研究過程中,開發(fā)人員們逐漸實現(xiàn)了相似的查詢語言,然后互想取長補短,最終在ODMG組織(www.odmg.org)的統(tǒng)一下,形成了規(guī)范化的語言:ODMG OQL,這是一種完全面向?qū)ο蟮臄?shù)據(jù)庫查詢語言,語法與前面提到的類似,不過考慮了更廣泛的情況,語句更加簡潔而嚴(yán)謹(jǐn)。 OQL并不是針對某種語言的,它可以被應(yīng)用到很多種開發(fā)語言中,它不象SQL那樣只是純字符串式的查詢語句,因為面向?qū)ο蟛樵冎羞€必須提供相關(guān)類的信息,所以O(shè)QL需要在編程語言中實現(xiàn)一些特定的API。 目前,ODMG的OQL已經(jīng)被規(guī)范化地應(yīng)用到SmallTalk、Java、C++這些面向?qū)ο蟮某绦蛟O(shè)計語言當(dāng)中,在ODMG的規(guī)范中,這幾個模塊被稱作SmallTalk Binding、Java Binding和C++ Binding。 不過,由于歷史原因,ODMG并沒有象想象中地那樣得到廣泛應(yīng)用,現(xiàn)有的十幾個面向?qū)ο髷?shù)據(jù)庫中,采用ODMG OQL規(guī)范的少之又少,目前也只有FastObjeccts、Ozone這些產(chǎn)品采納了這個規(guī)范,而象Versant這樣的大廠商還沒有采取OQL來查詢數(shù)據(jù)庫,而是自己定義了自己的一套API,稱作VQL(Versant Query Lanaguage)。 在JDO之前的O/R Mapping產(chǎn)品中,也有一些產(chǎn)品使用OQL(有時候是其子集),比如Castor、Apache的Jakarta小組開發(fā)的OJB等等。
3.2.2 第三方協(xié)議 軟件世界是一個多姿多彩的世界,總有那么一些好事之士不斷地冒出新奇的想法。還有一些開發(fā)面向?qū)ο髷?shù)據(jù)庫的組織制定了自己的一套對象式數(shù)據(jù)庫查詢語言,自己的規(guī)范。 不過這些規(guī)范相對來說,影響力小得多。比起ODMG來,可以說應(yīng)用范圍太小,更不用說與SQL這樣廣泛應(yīng)用的標(biāo)準(zhǔn)進(jìn)行比較了。
3.2.3 EJBQL Sun為了使Java應(yīng)用在企業(yè)級數(shù)據(jù)庫應(yīng)用中,不遺余力地推廣J2EE,在2001年的時候,推出了EJB2.0規(guī)范,其中包含了富有特色的面向CMP方式的EntityBean的查詢語言:EJBQL,功能類似于ODMG OQL,只不過只能在EJB發(fā)布時靜態(tài)地存在于應(yīng)用描述符中,不能在程序中動態(tài)地使用。這是EJBQL最大的弱點,也許EJB3.0規(guī)范會將其動態(tài)化,但到了那一天,世界多半已經(jīng)不是現(xiàn)在的樣子了。
3.2.4 JDO JDO中有最近規(guī)定的一個對象式查詢語言規(guī)范,稱作JDOQL,比起OQL來,JDOQL將查詢語言中的很多元素與Java語言緊密地結(jié)合在一起,有的人覺得麻煩,有些人覺得規(guī)范,評論各不相同。從筆者個人的角度來看,這樣有利于沒寫過數(shù)據(jù)庫應(yīng)用、沒用過SQL的新手很快地習(xí)慣JDOQL,但實際上,有多少人會在沒寫過SQL,沒了解過關(guān)系數(shù)據(jù)庫的情況下去用JDO寫數(shù)據(jù)庫應(yīng)用呢?畢竟市場說明了一切。個人認(rèn)為,JDO中對數(shù)據(jù)庫對象的查詢多少顯得有些累贅,如果能更簡化一點,那將更吸引使用傳統(tǒng)SQL的開發(fā)人員。
4 JDO歷程與主要產(chǎn)品 說起JDO,其來由還有一段特殊的背景。Java語言在JDK1.1達(dá)到比較實用的目的后,企業(yè)級數(shù)據(jù)庫應(yīng)用也正是軟件開發(fā)市場中的重要組成部分,Sun看到這一點后,也希望通過Java這個強大的武器在數(shù)據(jù)庫開發(fā)市場攻占市場份額。JDK1.2推出后,Sun同時推出了面向企業(yè)應(yīng)用的EJB,對基于java的中間件服務(wù)器框架進(jìn)行了規(guī)范化定義,這就是J2EE。不過在JDK1.2時,Java的速度還是不能與傳統(tǒng)的C/C++和Delphi這樣一些應(yīng)用開發(fā)語言相比。為了防止業(yè)界對Java的激情因此而消退,Sun宣布將在JDK中加入強大的虛擬機技術(shù)HotSpot,其中包含更先進(jìn)的垃圾收集算法和更優(yōu)化的Java字節(jié)代碼再編譯技術(shù)(相當(dāng)于JIT,Java即時編譯技術(shù))。HotSpot引起了Java關(guān)注者的極大興趣,但Sun的HotSpot一拖再拖,最后包含在JDK1.3中出來時,性能也沒有象預(yù)期的那樣好,比起C++編譯生成的代碼來還是有一段距離。 這個時候,大家開始對Sun心存懷疑,而Sun深知這一點,于是將公眾的注意力趕緊轉(zhuǎn)移到EJB上,從EJB1.0到EJB1.1,再到EJB2.0,業(yè)界又開始關(guān)注J2EE中間件技術(shù)上來。很快,開發(fā)人同發(fā)現(xiàn)用EJB來編寫數(shù)據(jù)庫應(yīng)用還是有很大的難度,雖然在分布式技術(shù)上EJB確實有很大的價值。在這個時候,Sun決定推出JDO技術(shù)作為輕量級的Java數(shù)據(jù)庫訪問規(guī)范,而這一點也受到很多傳統(tǒng)O/R Mapping市場的歡迎。為了與傳統(tǒng)O/R Mapping有所區(qū)別,Sun一開始就高姿態(tài)地將JDO定位成不只是面向關(guān)系數(shù)據(jù)庫的Java規(guī)范,而是針對所有的存儲技術(shù),包括面向?qū)ο髷?shù)據(jù)庫和其它類型的存儲體系(如文件),就象EJB EntityBean一樣,雖然。就筆者的角度,這個做法使第一版的JDO拋棄了很多傳統(tǒng)O/R Mapping提供的面向關(guān)系數(shù)據(jù)庫的功能,可以算是一個失策。
4.1 規(guī)范提出、JSR JDO最早是由Sun召集眾多的O/R Mapping開發(fā)團隊集中起來共同提出的,首先是通過會議確定了JDO需要包括的內(nèi)容,然后正式提出一個Java規(guī)范請求(JSR-12),正式開始了JDO規(guī)范的制定。下面是主要的進(jìn)展里程碑。 JSR #000012 approved in July 1999 1999-8組建的專家小組:包括Sun、Apple、BEA、IBM、Oracle、SAP、WebGain等 2000-5 完成公開評論草案 2000-6 在JavaOne上引入 2001-3 最終草案0.93 2001-5 最終草案0.96公布 2001-6 在JavaOne上啟動 2001-11 最終草案0.98 2002-4 1.0版正式公布 2002-8 1.0.1修正版 2003-8 2.0規(guī)范啟動 …
4.2 Oracle與JDO 作為JDO專家組的重要成員,同時作為最大的關(guān)系數(shù)據(jù)庫廠商的Oracle地位顯然非同一般。在JDO規(guī)范中,Oracle也可說是立下汗馬功勞,很多API的形成,Oracle都提供了很重要的參考意見,最終的投票O(jiān)racle也是毫不猶豫。 可是,世間的事總是變化莫測的,就在JDO1.0快出臺之時,Oracle收購了TopLink,這一點使Oracle的身份變得特殊而復(fù)雜。TopLink是一個商業(yè)產(chǎn)品,是以商業(yè)利益為目標(biāo)的,而Oracle也是追求利益最大化的典型商家,這一點與JDO的開放精神背道而馳。因此,我們看到后期Oracle對JDO的不積極態(tài)度,甚至在前一陣的JavaOne大會上有人從Oracle的角度非正式地攻擊JDO。
4.3 主要產(chǎn)品以及各自特點 在JDO規(guī)范制定的同時,出現(xiàn)了幾個主要的JDO產(chǎn)品,有美國的基于對象數(shù)據(jù)庫的FastObjects j1、法國的支持Versant對象數(shù)據(jù)庫、文件數(shù)據(jù)庫、主流RDBMS的LiDO、南非的JDOGenie、德國的JRelay等等,這些都是很不錯的JDO產(chǎn)品。下面列舉一下我對主要的幾個產(chǎn)品的印象: ? LiDO(法國LibeLis公司) 我對JDO的認(rèn)識主要是通過LiDO這個產(chǎn)品,它在2002年3月的一份圖文并茂的教程中簡要解說了JDO的使用和優(yōu)點。這個教程可以在這里下載:http://www.objectweb.org/conference/JDO.pdf。LiDO的特色是大而全,支持文件型數(shù)據(jù)庫、RDBMS、ODBMS,甚至是XML數(shù)據(jù)庫。不過配置較麻煩。最新版本是2.0RC。 ? KodoJDO(美國SolarMetrics公司) Kodo是JDO的中流砥柱之一,在JDO1.0還未最后通過的時候,它就是一個比較成熟的產(chǎn)品了,其特點是注重性能和穩(wěn)定性,目前最新版本是2.5.0,是客戶最多的產(chǎn)品。 ? JDOGenie(南非HemSphere公司) 這是目前我最推薦的產(chǎn)品,最新版本是1.4.7,性能也不錯,穩(wěn)定性還有待驗證,但它有一個最大的特點:集成性好,最易學(xué),其公司的CTO David Tinker也是一個善解人意的年輕人,采納了很多網(wǎng)友的意見對產(chǎn)品進(jìn)行改進(jìn),主要是在配置上非常方便,有一個專門的圖形界面工具,可以進(jìn)行配置、數(shù)據(jù)庫生成、對象查詢等等很實用的功能。 ? JRelay(德國ObjectIndustries公司) 這也是一個出現(xiàn)得比較早的產(chǎn)品,也有一個GUI工具用于配置,曾幾何時,這個工具還是相對很方便的,但一年多過去了,好象沒什么進(jìn)展,最新版本是2.0,我試過一段時間,后來就沒有再跟進(jìn)了。 ? FrontierSuite for JDO (美國ObjectFrontier) 這個產(chǎn)品與JRelay、Kodo一起,可算是早期的JDO三個主要產(chǎn)品,它支持正向開發(fā)和反向開發(fā)(Reverse Engineer)。它的特色是反向工程(從表結(jié)構(gòu)生成數(shù)據(jù)類)比較方便,與UML的結(jié)合也很強,不過真正運行起來的時候,配置復(fù)雜。 ? TJDO(一群跨國界的有志之士) 這是一個在Sun提供的參考產(chǎn)品(Reference Implementation)的基礎(chǔ)上加入一些擴展功能而形成的一個免費產(chǎn)品,目前最新版本是2.0beta3,不過進(jìn)展也緩慢,這個版本已經(jīng)出現(xiàn)好幾個月了沒有進(jìn)一步的更新。
5 目前狀況與未來展望 從2002年4月JDO1.0規(guī)范正式公布以來,各個產(chǎn)品層出不窮,從商業(yè)到免費的層次,都有不錯的產(chǎn)品推出。象Kodo、Lido、JDOGenie等產(chǎn)品都已經(jīng)比較成熟,可以考慮投入開發(fā)使用。在2002年8月,JDO又推出1.0.1修正版,修正了1.0版規(guī)范中的一些文字錯誤,以及輕微地改進(jìn)了部分異常定義,不過改動都不大。從現(xiàn)在的情形來看,除了Kodo有一些大學(xué)的項目用到外,好象還沒看到多少使用JDO作開發(fā)的應(yīng)用。 JDO畢竟是一個新技術(shù),從概念上到實際應(yīng)用上對其掌握的用戶還不多,而這些產(chǎn)品在配置、使用上的方便性易用性還有待大幅度改進(jìn),因此,真正用JDO來開發(fā)項目的用戶還廖廖無幾,至少我還不知道有哪些項目使用了JDO。我自己也嘗試使用JDO來開發(fā)項目,但由于一些JDO1.0版本中還不夠完善的一些硬傷(比如不支持關(guān)系數(shù)據(jù)庫統(tǒng)計功能),使我對JDO仍處于觀望階段。 在八月中旬進(jìn)行的JDO2.0規(guī)劃會議中,來自各國的各個JDO產(chǎn)品廠商、JDO技術(shù)咨詢公司、JDO研究機構(gòu)的代表匯聚一堂,將各自收集到的用戶對JDO2.0的需求總結(jié)起來,提出一個個的新的議題,并且確定了每個議題的JDO規(guī)范撰寫負(fù)責(zé)人,比如高級fetchGroup特性由目前實現(xiàn)得最好的JDOGenie的CTO David Tinker負(fù)責(zé),關(guān)于managed-relationship特性由Kodo的產(chǎn)品總監(jiān)負(fù)責(zé),用戶要求最多的JDO對象與PersistenceManager的脫鉤/重掛鉤特性由Sun的Craig Russell親自操刀,等等。 最具有吸引力的JDO2.0議題,筆者個人認(rèn)為是專門為關(guān)系數(shù)據(jù)庫設(shè)立的子規(guī)范JDO/R,這也是我一直以來最關(guān)心的,這將使目前JDBC的開發(fā)將可以被JDO完全取代,并且保證開發(fā)過程保持面向?qū)ο蟮奶厣_€有一些將一個類映射到多個表之類的特性也在規(guī)范化的列表上,這將有利于DBA在不影響應(yīng)用開發(fā)的前提下根據(jù)需要更改數(shù)據(jù)表結(jié)構(gòu),實現(xiàn)更好的性能。類似的新特性還有很多,粗略地看,這些都規(guī)范化起來后,真不知道各個廠商還能做什么樣的擴展特性,也許以后廠商之間拼的只能是技術(shù)支持服務(wù)和產(chǎn)品性能了,當(dāng)然,最后還有價格的競爭。 說了這么多,我想大家關(guān)心的還是JDO2.0到底什么時候能出來,我們什么時候可以用上它,什么時候有中文版產(chǎn)品,價格到底如何。這些問題目前筆者還無法一一回答,只能根據(jù)筆者所掌握的信息初步解釋一下。據(jù)前幾天的JDO2.0啟動大會上David Jordan的預(yù)期,JDO2.0正式版將在18個月后正式完成。那正式完成后廠商什么時候才能提供符合規(guī)范的產(chǎn)品呢?這個問題不用擔(dān)心,因為規(guī)范在制定的過程中會不斷地公布公眾預(yù)覽版(Public Review),這樣,廠商可以先實現(xiàn)其中的功能,等規(guī)范正式完成后,也不會有太大的變化,廠商也不會需要太多時間來跟進(jìn)最終規(guī)范。所以,我估計一年之后,我們就可以在JDO2.0上進(jìn)行開發(fā)了。至于價格如何,1.0規(guī)范的產(chǎn)品初步印象是每個開發(fā)人員需要一個License,一個License大概2000美元。如果JDO2.0產(chǎn)品的價格還保持這么貴的話(至少對中國用戶來說),我們也還有很多免費(如JPOX,TJDO)或半免費(如JCredo)產(chǎn)品可以選擇。最后一個關(guān)于中文版的問題,有待于廠商對中國市場的考察,或者看看是否有國內(nèi)的JDO產(chǎn)品了。不過,在JDO2.0規(guī)范制定的同時,我們可以先集眾人之力將其普及,使廣大的使用Java語言進(jìn)行數(shù)據(jù)庫開發(fā)的開發(fā)人員都來認(rèn)識JDO,了解JDO,甚至將其用到項目開發(fā)之中。 也許,JDO的目標(biāo)已經(jīng)吸引了Java世界以外的人,微軟發(fā)現(xiàn)了這一點,也立即計劃在.NET體系中加入一個仿照J(rèn)DO的中間件,具體是采用ObjectStore的產(chǎn)品,ObjectStore是一個同時做JDO和.NET-DO(姑且使用這個名稱)的公司。
在這里,筆者可以大膽地預(yù)測,在未來的一兩年內(nèi),JDO將在Java世界大放光彩!
5.1 一點花絮 在2003年6月舉行的JavaOne大會上,JDO備受矚目,很多開發(fā)者或開發(fā)組織對其產(chǎn)生了極大的興趣,在各大網(wǎng)站媒體上也頻頻曝光,大多對其評價不錯,當(dāng)然,也有一些負(fù)面的評價。 不過,網(wǎng)站上的報道也不可盡信,比如服務(wù)器領(lǐng)域的權(quán)威網(wǎng)站TheServerSide.com上介紹JavaOne大會第二天關(guān)于JDO的一次會議的報道就有誤導(dǎo)之嫌,從報道的內(nèi)容來看,好象會議用來答疑與交流的的最后五分鐘全被一個好事者占據(jù),這個人拼命鼓吹Oracle的TopLink解決方案和一些易用性的改進(jìn),從而攻擊JDO的市場前景。后來,我就這一信息與參加會議的JDO專家組的David Jordan交流時,他糾正了我的錯誤理解,實際情形是:那個好事者是一個積極的JDO擁護(hù)者,他花了超過五分鐘時間向大家揭露Oracle的TopLink改進(jìn)實際上也是抄襲JDO的概念而進(jìn)行的一些API改動!不過有一點是相同的,這個好事者占據(jù)了大家的提問時間,使這次會議在意猶未盡中結(jié)束。
本文的版權(quán)屬于筆者本人,但歡迎轉(zhuǎn)載,前提是注明出處和原作者。另外,歡迎在我的專欄中查看我的另幾篇文章,并提出寶貴意見!
| |