面向 Java 开发人员的 db4o 指南: 简介和概览
在我出道成為程序員的時候,數(shù)據(jù)庫之戰(zhàn)似乎已完全平息。Oracle 和其他幾個數(shù)據(jù)庫供應商都非常支持和看好關系模型及其標準查詢語言 SQL。實際上,坦率地講,我從未將任何關系數(shù)據(jù)庫的直接祖先,比如 IMS 或無處不在的平面文件,用于長期存儲。客戶機/服務器看起來似乎長久不衰。
之后,忽然有一天,我發(fā)現(xiàn)了 C++。正像許多在這個特別的時刻發(fā)現(xiàn)了這個特別的語言的其他人一樣,它改變了我的整個編程 “世界觀”。我的編程模型從基于函數(shù)和數(shù)據(jù)的變成了基于對象的。一時間,再也聽不到開發(fā)人員大談構建優(yōu)雅的數(shù)據(jù)結構和 “信息隱藏” 了,現(xiàn)在,我們更熱衷于多態(tài)、封裝 和繼承 —— 一整套新的熱門字眼。
|
與此同時,關系數(shù)據(jù)庫已風光不再,一種新的數(shù)據(jù)庫 —— 對象數(shù)據(jù)庫 —— 成為了人們的新寵。若能再結合一種面向?qū)ο蟮恼Z言,例如 C++ (或與之類似的編程新貴,Java 編程),OODBMS 真是可以堪稱編程的理想王國。
但是,事情的發(fā)展并非如此。OODBMS 在 90 年代晚期達到了頂峰,隨后就一直在走下坡路。原來的輝煌早已退去,剩下的只有晦澀和局限。在第二輪的數(shù)據(jù)庫之戰(zhàn)結束之時,關系數(shù)據(jù)庫又成了贏家。(雖然大多數(shù) RDBMS 供應商都或多或少地采用了對象,但這不影響大局。)
上述情況中存在的惟一問題是,開發(fā)人員對 OODBMS 的熱衷一直沒有衰退,db4o 的出現(xiàn)就很好地說明了這一點。
對象和關系
對象關系型阻抗失配 這個話題完全可以拿出來進行學術討論,但簡單說來,其本質(zhì)是:對象系統(tǒng)與關系系統(tǒng)在如何處理實體之間的互動方面所采取的方式是截然不同的。表面上看,對象系統(tǒng)和關系系統(tǒng)彼此非常合適,但若深入研究,就會發(fā)現(xiàn)二者存在本質(zhì)差異。
首先,對象具有身份的隱式性質(zhì)(其表征是隱藏/隱式的 this 指針或引用,它實際上是內(nèi)存的一個位置),而關系則具有身份的顯式性質(zhì)(其表征是組成關系屬性的主鍵)。其次,關系數(shù)據(jù)庫通過隱藏數(shù)據(jù)庫范圍內(nèi)的數(shù)據(jù)查詢和其他操作的實現(xiàn)進行封裝,而對象則在每個對象上實現(xiàn)新的行為(當然,模塊所實現(xiàn)的繼承都在類定義中進行指定)。另外,可能也是最有趣的是,關系模型是個封閉的模型,其中任何操作的結果都將產(chǎn)生一個元組集,適合作為另一個操作的輸入。這就使嵌套的 SELECT 以及很多其他功能成為可能。而對象模型則無此能力,尤其是向調(diào)用程序返回 “部分對象” 這一點。對象是要么全有要么全無的,其結果就是:與 RDBMS 不同,OODBMS 不能從表或一組表返回任一、全部或部分列。
簡言之,對象(用像 Java 代碼、C++ 和 C# 這類語言實現(xiàn))和關系(由像 SQLServer、Oracle 和 DB/2 這樣的現(xiàn)代 RDBMS 實現(xiàn))操作的方式有極大的差異。對于減少這種差異,程序員責無旁貸。
映射的作用
過去,開發(fā)人員曾試圖減少對象和關系間的這種差距,嘗試過的方式之一是手動映射,比如通過 JDBC 編寫 SQL 語句并將結果收集進字段。對這種方式的一個合理的質(zhì)疑是:是否還有更簡化的方法來進行處理。開發(fā)人員大都用自動的對象關系映射實用工具或庫(比如 Hibernate)來解決這個問題。
即使是通過 Hibernate(或 JPA、JDO、Castor JDO、Toplink 或任何可用的其他 ORM 工具),映射問題也無法徹底解決,它們只會轉(zhuǎn)移到配置文件。而且,這種方式與要解決的問題頗有些風馬牛不相及。比方說,如果您想要創(chuàng)建一個分層良好的繼承模型,將它映射到表或一組表無疑是失敗之舉。若用對常規(guī)形式的違背來換取查詢的性能,就會將 DBA 與開發(fā)人員在某種程度上對立起來。
可問題是很難構建一個富域模型(參見 Martin Fowler 和 Eric Evans 各自所著的書),不管是您以后想要調(diào)整它來匹配現(xiàn)有的數(shù)據(jù)庫模式,還是想要調(diào)整數(shù)據(jù)庫執(zhí)行其操作的功能來支持對象模型(甚或這兩者)。
但如果能不調(diào)整,豈不是更好?
進入 db4o:OODBMS 的回歸
db4o 庫是最近才出現(xiàn)在 OODBMS 領域的,它使 “純對象存儲” 的概念在新一代對象開發(fā)人員中重獲新生。(他們笑稱,現(xiàn)在不是很流行懷舊么。)為了讓您對如何使用 db4o 有一個概念,特給出如下代表單個人的一個基本類:
注意:如果還尚未下載,請現(xiàn)在就 下載 db4o。為了更好地進行討論(或至少編譯代碼),db4o 是必需的,本系列的后續(xù)文章也會用到它。
清單 1. Person 類
| package com.tedneward.model;public class Person {public Person(){ }public Person(String firstName, String lastName, int age){this.firstName = firstName;this.lastName = lastName;this.age = age;}public String getFirstName() { return firstName; }public void setFirstName(String value) { firstName = value; }public String getLastName() { return lastName; }public void setLastName(String value) { lastName = value; }public int getAge() { return age; }public void setAge(int value) { age = value; }public String toString(){return "[Person: " +"firstName = " + firstName + " " +"lastName = " + lastName + " " +"age = " + age + "]";}public boolean equals(Object rhs){if (rhs == this)return true;if (!(rhs instanceof Person))return false;Person other = (Person)rhs;return (this.firstName.equals(other.firstName) &&this.lastName.equals(other.lastName) &&this.age == other.age);}private String firstName;private String lastName;private int age; } |
在眾多的類中,Person 類顯得極為尋常;還很簡單。但若深入探究,就不難看出這個類會呈現(xiàn)出非常類似于對象的有趣屬性和功能,例如它可以有配偶類,也可以有子類,等等。(我在后續(xù)的專欄中會歷數(shù)這些屬性和功能;現(xiàn)在,我只側重于進行概括介紹。)
在基于 Hibernate 的系統(tǒng)中,將這個 Person 類的一個實例放入數(shù)據(jù)庫,需要如下幾個步驟:
上述操作在 db4o 中出奇地簡單,如清單 2 所示:
清單 2. 在 db4o 內(nèi)運行 INSERT
| import com.db4o.*;import com.tedneward.model.*;public class Hellodb4o {public static void main(String[] args)throws Exception{ObjectContainer db = null;try{db = Db4o.openFile("persons.data");Person brian = new Person("Brian", "Goetz", 39);db.set(brian);db.commit();}finally{if (db != null)db.close();}} } |
這樣就行了。無需生成模式文件,無需創(chuàng)建映射配置,需要做的只是運行客戶機程序,當運行結束時,為存儲在 persons.data 中的新 “數(shù)據(jù)庫” 檢查本地目錄。
檢索所存儲的 Person 在某些方面非常類似于某些對象關系型映射庫的操作方式,原因是對象檢索最簡單的形式就是按例查詢(query-by-example)。只需為 db4o 提供相同類型的一個原型對象,該對象的字段設置為想要按其查詢的值,這樣一來,就會返回匹配該條件的一組對象,如清單 3 所示:
清單 3. 在 db4o 內(nèi)運行 INSERT(版本 1)
| import com.db4o.*;import com.tedneward.model.*;public class Hellodb4o {public static void main(String[] args)throws Exception{ObjectContainer db = null;try{db = Db4o.openFile("persons.data");Person brian = new Person("Brian", "Goetz", 39);Person jason = new Person("Jason", "Hunter", 35);Person clinton = new Person("Brian", "Sletten", 38);Person david = new Person("David", "Geary", 55);Person glenn = new Person("Glenn", "Vanderberg", 40);Person neal = new Person("Neal", "Ford", 39);db.set(brian);db.set(jason);db.set(clinton);db.set(david);db.set(glenn);db.set(neal);db.commit();// Find all the BriansObjectSet brians = db.get(new Person("Brian", null, 0));while (brians.hasNext())System.out.println(brians.next());}finally{if (db != null)db.close();}} } |
運行上述代碼,會看到檢索出兩個對象。
但是...
在您將我定義為狂熱的推崇者之前,請允許我先列舉幾條反對 db4o 的言論。
db4o 幾乎無法對應于現(xiàn)有的 Oracle、SQLServer 或 DB2!對于 db4o 不支持的語言,比如 C++ 或 Python,數(shù)據(jù)基本上是訪問不到的,除非是您能從 Java 代碼構建程序。db4o 適用于 C# 和其他的 .NET 語言,而其數(shù)據(jù)格式在二者之間是兼容的,這就使得 Java 對象對同樣定義的 .NET 類也可用。如果您這里所謂的 “其他程序” 指的是使用 SQL 和標準調(diào)用級接口(比如 ODBC 或 JDBC)來與數(shù)據(jù)庫進行交互的報告工具,那么 db4o(或與此相關的任何 OODBMS)可能未必是很好的選擇。機警的讀者會發(fā)現(xiàn)報告功能現(xiàn)在對 OODBMS 還不可用,但好消息是:已針對此問題發(fā)起很多產(chǎn)品和項目,而且 db4o 還支持 “復制(Replication)”,它允許 db4o 實例將數(shù)據(jù)從其自身的存儲格式復制進 RDBMS。
當創(chuàng)建新對象并將其 “放” 進數(shù)據(jù)庫中時,新對象并不具有與其相關的 OID,因而會收到其自身惟一的 OID 值。它會復制,就如同 RDBMS 在執(zhí)行每個 INSERT 操作時生成主鍵所做的那樣(比如 順序計數(shù)器或自動增量字段)。換言之,就主鍵而言,OODBMS 與 RDBMS 相當接近,但主鍵本身并非傳統(tǒng) RDBMS(或過去習慣使用 RDBMS 的程序員)認為的那種主鍵。
換言之,db4o 旨在解決某些方面的問題,而不是成為解決全部持久性問題的一站式通用解決方案。實際上,這讓 db4o 首輪就戰(zhàn)勝了 OODBMS:db4o 無意向那些生產(chǎn) IT 人員宣稱自己是多么好的一種理念,以至于完全可以放棄他們在關系數(shù)據(jù)庫上的投資。?
?
結束語
傳統(tǒng)的集中關系型數(shù)據(jù)庫作為數(shù)據(jù)存儲和操縱的首選工具的地位在短期內(nèi)無法撼動。以這種數(shù)據(jù)庫為基礎發(fā)展起來的工具非常之多,歷史也很久遠,而且許多程序員也都陷在 “我們總需要數(shù)據(jù)庫” 的思維模式之中,這些無疑加固了其地位。實際上,db4o 在技術上的設計和定位并不是為了挑戰(zhàn) RDBMS 的這一地位。
但 “面向服務” 社區(qū)迫切要求我們構建松散耦合的多層世界,當您開始將 OODBMS 放到這種環(huán)境中去審視的時候,有趣的現(xiàn)象就出現(xiàn)了:如果要實現(xiàn)組件(服務、層或諸如此類的東西)間真正的松散耦合,那么結果常常是某種程度的耦合只存在于服務的調(diào)用程序和該服務的公開 API(或 XML 類型,不管您如何看待它)之間。無需數(shù)據(jù)類型,無需公開對象模型,無需共享數(shù)據(jù)庫 —— 本質(zhì)上講,持久性方法僅僅是一個實現(xiàn)細節(jié)。因此,在大量場景中可用的持久性方法的范圍會顯著擴大。
總結
以上是生活随笔為你收集整理的面向 Java 开发人员的 db4o 指南: 简介和概览的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言实现调和平均数
- 下一篇: Java 文件传输 (TCP、UDP)