面向?qū)ο髷?shù)據(jù)庫db4o之旅_第1頁
面向?qū)ο髷?shù)據(jù)庫db4o之旅_第2頁
面向?qū)ο髷?shù)據(jù)庫db4o之旅_第3頁
面向?qū)ο髷?shù)據(jù)庫db4o之旅_第4頁
面向?qū)ο髷?shù)據(jù)庫db4o之旅_第5頁
已閱讀5頁,還剩33頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、面向?qū)ο髷?shù)據(jù)庫 db4o 之旅第 1 部分: 初識 db4oRosen Jiang, 軟件工程師, db4o 和 OO 的忠實(shí) fansRosen Jiang 來自成都,是 db4o 和 OO 的忠實(shí) fans,是 2005 年 db4o 的 dvp 獲得者之一。他正在 J2me 應(yīng)用中使用 db4o,你可以通過 rosener_722 和他聯(lián)系。張 黃矚 (zhanghuangzhugmailcom), 軟件工程師, 熱愛開源軟件張黃矚,熱愛開源軟件,熟悉 Java/C/C+ 編程語言,對數(shù)據(jù)庫技術(shù)網(wǎng)絡(luò)技術(shù)均感興趣。你可以通過 zhanghuangzhu 聯(lián)系他。Chris (chrisMa

2、trixorgcn), Matrix 創(chuàng)辦者, MatrixChris 來自香港,熱愛開源和 db4o。他創(chuàng)辦了中國最火熱的 Java 和開源社區(qū) Matrix(http:/www.M), 你可以通過 chrisM 和他聯(lián)系。簡介: 本文為 db4o 之旅 系列文章的第一篇,介紹了面向?qū)ο髷?shù)據(jù)庫 db4o 的基本特性,并且與傳統(tǒng)關(guān)系型數(shù)據(jù)庫以及 OR 映射技術(shù)做了比較分析,讀者可以體驗(yàn)到 db4o 的全新的面向?qū)ο蟠鎯Φ睦砟?,并且給出了性能測試數(shù)據(jù)。前言業(yè)界對持久存儲領(lǐng)域的追求從未停止過,為了更方便、更容易地用對象表達(dá)我們的思維,開源領(lǐng)域和商業(yè)領(lǐng)域都涌現(xiàn)了許多新技術(shù), ORM 的出現(xiàn)

3、恰恰說明了這點(diǎn)。最近一年,業(yè)界也在反思,到底 ORM 給我們帶來的是便利還是麻煩。矛頭指向大名鼎鼎的 Hibernate ,紛紛議論其性能問題,大家似乎要達(dá)成這樣的共識:“在業(yè)務(wù)邏輯復(fù)雜的地方用 SP ,而一般的 CRUD 還是 Hibernate ”,就連全球知名的 BearingPoint 也有類似看法。下面一個簡單的例子,說明了傳統(tǒng) ORM 工具的弊端。讓我們考慮一個簡單的 Student 對象如清單1:清單1 Student 類public class Student private String name; private int age; public String getName

4、() return name; public int getAge() return age; 考慮下面這個場景:找到“年齡小于 20 歲的所有學(xué)生”?使用 ORL 實(shí)現(xiàn)如清單2:清單2 ORL 實(shí)現(xiàn)String oql = "select * from student in AllStudents where studentage <20" OQLQuery query = new OQLQuery(oql); Object students = queryexecute(); 使用 JDOQL 實(shí)現(xiàn)如清單3:清單3 JDOQL 實(shí)現(xiàn)Query query = pe

5、rsistenceManagernewQuery(Studentclass, "age <20"); Collection students = (Collection)queryexecute(); 上面的方法都存在一些普遍問題: · 現(xiàn)代集成開發(fā)環(huán)境不會檢查內(nèi)嵌字符串的語義和語法錯誤。在上面所有查詢語句中, age 字段和數(shù)值 20 都被認(rèn)為是數(shù)字類型,但是沒有一個 IDE 或編譯器能檢查其實(shí)際正確性。如果開發(fā)者混淆了查詢代碼比如,改變了 age 字段的名字或類型,將導(dǎo)致上面所有的查詢語句在運(yùn)行時報錯,而不會在編譯時提示。 · 現(xiàn)代敏捷開發(fā)技術(shù)

6、鼓勵不斷進(jìn)行重構(gòu)來維持清晰和與時俱進(jìn)的類模型,以便準(zhǔn)確重現(xiàn)不斷演進(jìn)的域模型。如果查詢代碼難于維護(hù),它會延遲決定重構(gòu)的時間并不可避免的引入低質(zhì)量代碼。 · 所有列出的查詢都直接用 Student 類的私有成員 age,而不是使用它的公共接口 studentgetAge(),因此他們都破壞了面向?qū)ο蠓庋b規(guī)則,違反接口和實(shí)現(xiàn)應(yīng)該分離的面向?qū)ο蠓▌t。 · 所有的查詢都非 100% 的原生。 既然存在如此多的問題, 為什么不直接使用純面向?qū)ο髷?shù)據(jù)庫呢?有些開發(fā)者可能會說:“它缺乏數(shù)學(xué)模型的支持, 還不夠成熟”。的確, RDBMS 發(fā)展了幾十年才有今天的成就,已經(jīng)非常完善了。而技術(shù)的革

7、新是無止境的, 故步自封的永遠(yuǎn)都跟不上變化的腳步。 讓我們來簡單回顧一下對象數(shù)據(jù)庫的發(fā)展史(資料來源于 Wiki 百科全書):“面向?qū)ο髷?shù)據(jù)庫系統(tǒng)”這一術(shù)語第一次出現(xiàn)于 1985 年。著名的研究項(xiàng)目包括:Encore-Ob/Server ( 布朗大學(xué)), EXODUS(Wisconsin 大學(xué)), IRIS (惠普), ODE ( Bell 實(shí)驗(yàn)室), ORION (MCC ) ,Vodak (GMD-IPSI)和 Zeitgeist (Texas Instruments)。其中以 ORION 項(xiàng)目發(fā)表的論文數(shù)為最多。 MCC 的 Won Kim 將這些論文中最有價值的一部分匯編成書并由 MI

8、T 出版社出版。對象數(shù)據(jù)庫管理系統(tǒng)為面向?qū)ο缶幊陶Z言增加了持久的概念。最早的商品化 ODBMS 出現(xiàn)在 1986 年,是 Servio 公司(現(xiàn)在的 GemStone 公司)和 Ontos 公司推出的。后來(九十年代) Object Design ( ODI )、 Versant 、 Objectivity 、 O2 Technology 、 Poet 、 Ibex 、 UniSQL 和 ADB MATISSE 等公司也加入了這個開拓行列。而今天,一家來自加州硅谷的開源面向?qū)ο髷?shù)據(jù)庫公司 db4objects 為我們帶來了db4o, 一款性能卓越的純面向?qū)ο髷?shù)據(jù)庫,也是我們這篇和后續(xù)文章將會介

9、紹的主角。db4o 為我們帶來的是這樣一種面向?qū)ο蟮牟樵兎绞?· 100% 的原生 查詢語言應(yīng)能用實(shí)現(xiàn)語言( Java 或 C# )完全表達(dá),并完全遵循實(shí)現(xiàn)語言的語義。 · 100% 的面向?qū)ο?查詢語言應(yīng)可運(yùn)行在自己的實(shí)現(xiàn)語言中,允許未經(jīng)優(yōu)化執(zhí)行普通集合而不用自定義預(yù)處理。 · 100% 的類型安全 查詢語言應(yīng)能完全獲取現(xiàn)代 IDE 的特性,比如語法檢測、類型檢測、重構(gòu),等等。 什么是 db4o“利用表格存儲對象,就像是將汽車開回家,然后拆成零件放進(jìn)車庫里,早晨可以再把汽車裝配起來。但是人們不禁要問,這是不是泊車的最有效的方法呢?!?Esther Dyson d

10、b4o 是一個開源的純面向?qū)ο髷?shù)據(jù)庫引擎,對于 Java 與 NET 開發(fā)者來說都是一個簡單易用的對象持久化工具,使用簡單。同時,db4o 已經(jīng)被第三方驗(yàn)證為具有優(yōu)秀性能的面向?qū)ο髷?shù)據(jù)庫, 下面的基準(zhǔn)測試圖對 db4o 和一些傳統(tǒng)的持久方案進(jìn)行了比較。db4o 在這次比較中排名第二,僅僅落后于JDBC。通過圖 1 的基準(zhǔn)測試結(jié)果,值得我們細(xì)細(xì)品味的是采用 Hibernate/HSQLDB 的方案和 JDBC/HSQLDB 的方案在性能方面有著顯著差距,這也證實(shí)了業(yè)界對 Hibernate 的擔(dān)憂。而 db4o 的優(yōu)異性能,讓我們相信: 更 OO 并不一定會犧牲性能。圖1 HSQLDB 基準(zhǔn)測試

11、同時,db4o 的一個特點(diǎn)就是無需 DBA 的管理,占用資源很小,這很適合嵌入式應(yīng)用以及 Cache 應(yīng)用, 所以自從 db4o 發(fā)布以來,迅速吸引了大批用戶將 db4o 用于各種各樣的嵌入式系統(tǒng),包括流動軟件、醫(yī)療設(shè)備和實(shí)時控制系統(tǒng)。db4o 由來自加州硅谷的開源數(shù)據(jù)庫公司 db4objects 開發(fā)并負(fù)責(zé)商業(yè)運(yùn)營和支持。db4o 是基于 GPL 協(xié)議。db4objects 于 2004 年在 CEO Christof Wittig 的領(lǐng)導(dǎo)下組成,資金背景包括 Mark Leslie 、 Veritas 軟件公司 CEO 、 Vinod Khosla ( Sun 公司創(chuàng)始人之一)、 Sun

12、公司 CEO 在內(nèi)的硅谷高層投資人組成。毫無疑問,今天 db4objects 公司是硅谷炙手可熱的技術(shù)創(chuàng)新者之一。db4o 特性db4o 的目標(biāo)是提供一個功能強(qiáng)大的,適合嵌入的數(shù)據(jù)庫引擎,可以工作在設(shè)備,移動產(chǎn)品,桌面以及服務(wù)器等各種平臺。主要特性如下:· 開源模式。與其他 ODBMS 不同,db4o 為開源軟件,通過開源社區(qū)的力量驅(qū)動開發(fā) db4o 產(chǎn)品。 · 原生數(shù)據(jù)庫。db4o 是 100% 原生的面向?qū)ο髷?shù)據(jù)庫,直接使用編程語言來操作數(shù)據(jù)庫。程序員無需進(jìn)行 OR 映射來存儲對象,大大節(jié)省了程序員在存儲數(shù)據(jù)的開發(fā)時間。 · 高性能。 圖2為 db4o 官方公

13、布的基準(zhǔn)測試數(shù)據(jù),db4o 比采用 Hibernate/MySQL 方案在某些測試線路上速度高出 44 倍之多!并且安裝簡單,僅僅需要 400Kb 左右的 jar 或 dll 庫文件。在接下來的系列文章中,我們將只關(guān)注在 Java 平臺的應(yīng)用,但是實(shí)際上 db4o 毫無疑問會很好地在 NET 平臺工作。 圖2 db4o 官方基準(zhǔn)測試數(shù)據(jù)· 易嵌入。使用 db4o 僅需引入 400 多 k 的 jar 文件或是 dll 文件,內(nèi)存消耗極小。 · 零管理。使用 db4o 無需 DBA,實(shí)現(xiàn)零管理。 · 支持多種平臺。db4o 支持從 Java 11 到 Java 50

14、,此外還支持 NET 、 CompactFramework 、 Mono 等 NET 平臺,也可以運(yùn)行在 CDC 、 PersonalProfile 、 Symbian 、 Savaje 以及 Zaurus 這種支持反射的 J2ME 方言環(huán)境中,還可以運(yùn)行在 CLDC 、 MIDP 、 RIM/Blackberry 、 Palm OS 這種不支持反射的 J2ME 環(huán)境中。 或許開發(fā)者會問,如果現(xiàn)有的應(yīng)用環(huán)境已經(jīng)有了關(guān)系型數(shù)據(jù)庫怎么辦?沒關(guān)系,db4o 的 dRS(db4o Replication System)可實(shí)現(xiàn) db4o 與關(guān)系型數(shù)據(jù)庫的雙向同步(復(fù)制),如圖 3 。 dRS 是基于 H

15、ibernate 開發(fā),目前的版本是 10 ,并運(yùn)行在 Java 12 或更高版本平臺上,基于 dRS 可實(shí)現(xiàn) db4o 到 Hibernate/RDBMS 、 db4o 到 db4o 以及 Hibernate/RDBMS 到 Hibernate/RDBMS 的雙向復(fù)制。dRS 模型如圖3 圖3 dRS 模型結(jié)論db4o 因?yàn)槠溟_源的理念,以及創(chuàng)新的實(shí)現(xiàn),獲得了 Java Pro 2006 讀者選擇獎。無論從成功案例還是 db4o 本身來看,這款純面向?qū)ο髷?shù)據(jù)庫都值得我們關(guān)注,從官方論壇反饋情況看,有相當(dāng)?shù)挠脩魷?zhǔn)備把關(guān)系型數(shù)據(jù)庫遷移到 db4o 。而最新發(fā)布的 55 版本,更是把性能再次提升很

16、多。在接下來的文章中,我會繼續(xù)和大家分享 db4o 給我們帶來的這場面向?qū)ο髷?shù)據(jù)庫風(fēng)暴。第 2 部分: db4o 查詢方式Rosen Jiang, 軟件工程師, db4o 和 OO 的忠實(shí) fansRosen Jiang 來自成都,是 db4o 和 OO 的忠實(shí) fans,是 2005 年 db4o 的 dvp 獲得者之一。他正在 J2me 應(yīng)用中使用 db4o,你可以通過 rosener_722 和他聯(lián)系。Chris (chrisMatrixorgcn), Matrix 創(chuàng)辦者, MatrixChris 來自香港,熱愛開源和 db4o。他創(chuàng)辦了中國最火熱的 Java 和開源社區(qū) Matrix

17、(http:/www.M), 你可以通過 chrisM 和他聯(lián)系。張 黃矚 (zhanghuangzhugmailcom), 軟件工程師, 熱愛開源軟件張黃矚,熱愛開源軟件,熟悉 Java/C/C+ 編程語言,對數(shù)據(jù)庫技術(shù)網(wǎng)絡(luò)技術(shù)均感興趣。你可以通過 zhanghuangzhu 聯(lián)系他。簡介: 這篇文章是 db4o 之旅 系列文章的第二篇,介紹了面向?qū)ο髷?shù)據(jù)庫 db4o 的安裝、啟動以及三種查詢語言,并對三種查詢語言做了比較。查看本系列更多內(nèi)容標(biāo)記本文!前言在 db4o 之旅 系列文章的第一部分:初識 db4o 中,作者介紹了 db4o 的歷史和現(xiàn)狀,應(yīng)用領(lǐng)域,以及和 ORM 等的比

18、較。在這篇文章中,作者將會介紹 db4o 的安裝、啟動以及三種不同的查詢方式:QBE(Query by Example)、SODA(Simple Object Database Access) 以及 NQ(Native Queries),并分別通過這三種不同的途徑實(shí)現(xiàn)了兩個關(guān)聯(lián)對象的查詢。本文還示范了開發(fā)中最經(jīng)常用到的幾個典型功能的 db4o 實(shí)現(xiàn)。下載和安裝 db4odb4o 所有最新的版本都可以直接在官方網(wǎng)站上下載,進(jìn)入 db4o 的下載頁面,我們可以看到最新的 for Java 穩(wěn)定版本是 55,包括 JAR、源代碼、入門文檔、API 等內(nèi)容的完整的打包文件只有 6 MB,db4o 還有

19、一個對象數(shù)據(jù)庫管理工具 ObjectManager,目前版本是 18(請?jiān)趨⒖假Y源中下載)。接著在 Eclipse 中新建 Java 項(xiàng)目,把 db4o 對象數(shù)據(jù)庫引擎包 db4o-55-java5jar 導(dǎo)入進(jìn)項(xiàng)目。由于 db4o 支持多種版本的 JDK,除了 for JDK 50 的 db4o-55-java5jar 外,還有 for JDK 11、12-14 的 JAR 包,以適應(yīng)多種環(huán)境。與 Hibernate、iBATIS SQL Maps 相比,db4o 更加自然,無需過多地引用第三方支持庫。開啟數(shù)據(jù)庫db4o 怎樣進(jìn)行對象持久化呢?通過瀏覽目錄可以發(fā)現(xiàn),與傳統(tǒng)的 RDBMS 一樣

20、,db4o 也有自己的數(shù)據(jù)庫文件, 在 db4o 中數(shù)據(jù)庫文件的后綴名是“*yap”。讓我們先來了解一下 db4o 對象數(shù)據(jù)庫引擎的主要包結(jié)構(gòu):· comdb4o comdb4o 包含了使用 db4o 時最經(jīng)常用到的功能。兩個最重要的接口是 comdb4oDb4o 和 comdb4oObjectCdb4oDb4o 工廠是運(yùn)行 db4o 的起點(diǎn),這個類中的靜態(tài)方法可以開啟數(shù)據(jù)庫文件、啟動服務(wù)器或連接一個已經(jīng)存在的服務(wù)器,還可以在開啟數(shù)據(jù)庫之前進(jìn)行 db4o 環(huán)境配置。comdb4oObjectContainer 接口很重要,開發(fā)過程中 99% 的時間都會用到它,

21、ObjectContainer 可在單用戶模式下作為數(shù)據(jù)庫實(shí)例,也可作為 db4o 服務(wù)器的客戶端。每個 ObjectContainer 實(shí)例都有自己的事務(wù)。所有的操作都有事務(wù)保證。當(dāng)打開 ObjectContainer,就已經(jīng)進(jìn)入事務(wù)了,commit() 或 rollback() 時,下一個事務(wù)立即啟動。每個 ObjectContainer 實(shí)例維護(hù)它自己所管理的已存儲和已實(shí)例化對象,在需要 ObjectContainer 的時候,它會一直保持開啟狀態(tài),一旦關(guān)閉,內(nèi)存中數(shù)據(jù)庫所引用的對象將被丟棄。 · comdb4oext 你也許想知道為什么在 ObjectContainer 中只

22、能看見很少的方法,原因如下:db4o 接口提供了兩個途徑,分別在 comdb4o 和 comdb4oext 包中。這樣做首先是為了讓開發(fā)者能快速上手;其次為了讓其他產(chǎn)品能更容易的復(fù)制基本的 db4o 接口;開發(fā)者從這一點(diǎn)上也能看出 db4o 是相當(dāng)輕量級的。每個 comdb4oObjectContainer 對象也是 comdb4oextExtObjectContainer 對象??梢赞D(zhuǎn)換成 ExtObjectContainer 獲得更多高級特性。 · comdb4oconfig comdb4oconfig 包含了所有配置 db4o 所需的類。 · comdb4oquery

23、 comdb4oquery 包包含了構(gòu)造“原生查詢, NQ(Native Queries)”所需的 Predicate 類。NQ 是 db4o 最主要的查詢接口。 db4o 提供兩種運(yùn)行模式,分別是本地模式和服務(wù)器模式。本地模式是指直接在程序里打開 db4o 數(shù)據(jù)庫文件進(jìn)行操作:ObjectContainer db = Db4oopenFile("autoyap");而服務(wù)器模式則是客戶端通過 IP 地址、端口以及授權(quán)口令來訪問服務(wù)器:服務(wù)器端: ObjectServer server=Db4oopenServer("autoyap",1212);ser

24、vergrantAccess("admin","123456");客戶端: ObjectContainer db=Db4oopenClient("192168010",1212,"admin","123456");兩種方式都可以得到 ObjectContainer 實(shí)例,就目前 Java EE 應(yīng)用環(huán)境來看,服務(wù)器模式更有現(xiàn)實(shí)意義;而本地模式更適合于嵌入式應(yīng)用。為了簡化演示,本文在下面的例子都將采用本地模式。在下面的例子里,我們都會用到下面兩個對象: People 和 AutoInfo 對象。P

25、eople 對象清單1:清單1 People 對象package bo;public class People private javalangInteger _id;private javalangString _name;private javalangString _address;private javautilList<AutoInfo> _autoInfoList;public javalangInteger getId() return _id;public void setId(javalangInteger _id) this_id = _id;public ja

26、valangString getName() return _name;public void setName(javalangString _name) this_name = _name;public javalangString getAddress() return _address;public void setAddress(javalangString _address) this_address = _address;public javautilList<AutoInfo> getAutoInfoList() return this_autoInfoList;pu

27、blic void addAutoInfo(AutoInfo _autoInfoList) if (null = this_autoInfoList)this_autoInfoList = new javautilArrayList<AutoInfo>();this_autoInfoListadd(_autoInfoList);AutoInfo 對象清單2:清單2 AutoInfo 對象package bo;public class AutoInfoprivate javalangInteger _id;private javalangString _licensePlate;pr

28、ivate boPeople _ownerNo;public javalangInteger getId () return _id;public void setId (javalangInteger _id) this_id = _id;public javalangString getLicensePlate () return _licensePlate;public void setLicensePlate (javalangString _licensePlate) this_licensePlate = _licensePlate;public boPeople getOwner

29、No () return this_ownerNo;public void setOwnerNo (boPeople _ownerNo) this_ownerNo = _ownerNo;利用 set 方法把新對象存入 ObjectContainer,而對 ObjectContainer 中已有對象進(jìn)行 set 操作則是更新該對象。db4o 保存數(shù)據(jù)庫很簡單,下面就是一個段完整的保存對象的代碼:AutoInfo 對象清單3:清單3package com;import boAutoInfo;import boPeople;import comdb4oDb4o;import comdb4oObjec

30、tContainer;public class DB4OTestpublic static void main(String args)/打開數(shù)據(jù)庫ObjectContainer db = Db4oopenFile("autoyap");try/構(gòu)造 People 對象People peo = new People(); peosetId(1);peosetAddress("成都市");peosetName("張三");/構(gòu)造 AutoInfo 對象AutoInfo ai = new AutoInfo();aisetId(1);ais

31、etLicensePlate("川A00000");/設(shè)置 People 和 AutoInfo 的關(guān)系aisetOwnerNo(peo);peoaddAutoInfo(ai);/保存對象dbset(peo);finally/關(guān)閉連接dbclose();當(dāng)我們運(yùn)行上述代碼,db4o 會自動創(chuàng)建“autoyap”文件。讓我們來看看到底保存成功沒有,打開 ObjectManager 工具,如圖 1 所示。圖1 對象數(shù)據(jù)庫管理工具“File”>“Open File”>選擇剛才我們保存的“autoyap”文件(“autoyap”文件可在項(xiàng)目的根目錄下找到),最新的 Obj

32、ectManager 18 版本為我們提供了“Read Only”方式讀取數(shù)據(jù)庫文件,避免 ObjectManager 占用數(shù)據(jù)庫文件所導(dǎo)致的程序異常。打開之后,如圖 2 所示,剛才存貯的 People 對象已經(jīng)在數(shù)據(jù)庫中了,并且還可以很直觀的看到 AutoInfo 對象也放入了 ArrayList 中。這種可視化的對象關(guān)系有利于我們對數(shù)據(jù)的理解,是傳統(tǒng) RDBMS 無法比擬的。有些開發(fā)者會說 ObjectManager 工具略顯簡單,這點(diǎn)我想隨著 db4o 的不斷發(fā)展會加入更多的特性。在這個工具中,我們意外的發(fā)現(xiàn)了 Java 集合對象的蹤影,db4o 把與 ArrayList 有直接關(guān)系的所

33、有接口和父類都保存了,這樣顯得更直觀。在此,我保留了 _id 屬性,這是因?yàn)橥ǔT?Java EE 環(huán)境中,DAO 第一次不是把整個對象都返回到表現(xiàn)層,而是只返回了“標(biāo)題”、“發(fā)布時間”這些信息(并隱式的返回id),接著 DAO 與數(shù)據(jù)庫斷開;要查看詳情(比如文章內(nèi)容)就需要進(jìn)行 findById 操作,這時 DAO 要再次與數(shù)據(jù)庫交互,只有唯一標(biāo)識符才能正確地找到對象。這種懶加載方式也是很多書籍所推薦的?;氐奖疚牡姆独绦蛑校@個 _id 屬性可由人工編碼實(shí)現(xiàn)的“序列”進(jìn)行賦值,當(dāng)然 db4o 也提供了內(nèi)部標(biāo)識符 Internal IDs,如圖 2 中的 id=1669;以及 UUIDs。圖

34、2 對象結(jié)構(gòu)查詢數(shù)據(jù)庫和 RDBMS 一樣,db4o 也有自己的查詢語言,分別是 QBE(Query by Example)、NQ(Native Queries)、SODA(Simple Object Database Access),db4o 更推薦使用 NQ 進(jìn)行查詢。NQ 方式提供了非常強(qiáng)大的查詢功能,支持原生語言,也就意味著你可以使用 Java 來判斷該對象是否符合條件,這是其他數(shù)據(jù)庫查詢語言無法比擬的。在某些情況下, db4o 核心會將 NQ 翻譯成 SODA 以獲得更高的性能。下面詳細(xì)介紹一下這三種查詢語言。QBE(Query by Example)QBE 規(guī)范可在這里下載。QBE

35、 最初由 IBM 提出,同時業(yè)界也有許多和 QBE 兼容的接口,包括著名的 Paradox。有些系統(tǒng),比如微軟的 Access,它的基于表單的查詢也是受到了部分 QBE 思想的啟發(fā)。在 db4o 中,用戶可借用 QBE 快速上手,可以很容易適應(yīng) db4o 存取數(shù)據(jù)的方式。當(dāng)利用 QBE 為 db4o 提供模板(example)對象時,db4o 將返回所有和非默認(rèn)值字段匹配的全部對象。內(nèi)部是通過反射所有的字段和構(gòu)造查詢表達(dá)式(所有非默認(rèn)值字段結(jié)合”AND”表達(dá)式)來實(shí)現(xiàn)。例如,利用 QBE 查找到車牌號為“川A00000”的車主姓名,這是一個級聯(lián)查詢。清單4:清單4package com;imp

36、ort javautilList;import boAutoInfo;import comdb4oDb4o;import comdb4oObjectContainer;public class DB4OTestpublic static void main(String args)/打開數(shù)據(jù)庫ObjectContainer db = Db4oopenFile("autoyap");try/構(gòu)造模板對象AutoInfo ai = new AutoInfo();aisetLicensePlate("川A00000");/查詢對象List<AutoInf

37、o> list = dbget(ai); for(int x = 0; x < listsize(); x+) Systemoutprintln("車主姓名:"+listget(x)getOwnerNo()getName();finally/關(guān)閉連接dbclose();但是 QBE 也有明顯的限制:db4o 必須反射模板(example)對象的所有成員;無法執(zhí)行更進(jìn)一步的查詢表達(dá)式(例如 AND、OR、NOT 等等);不能約束 0(整型)、”(空字符串)或者 null(對象),因?yàn)檫@些都被認(rèn)為是不受約束的。要繞過這些限制,db4o 提供了 NQ(Native Q

38、ueries)。SODA(Simple Object Database Access)SODA ,簡單對象數(shù)據(jù)庫訪問,請查看官方站點(diǎn),其中一位主要維護(hù)者是 Carl Rosenberger,Carl 正是 db4o 首席架構(gòu)師。SODA 就是一種與數(shù)據(jù)庫通訊的對象 API。最終的目標(biāo)是實(shí)現(xiàn)類型安全、對象復(fù)用、最小的字符串使用、與編程語言無關(guān)等特性。SODA 是 db4o 最底層的查詢 API,目前 SODA 中使用字符串來定義字段,這樣將不能實(shí)現(xiàn)類型安全也無法在編譯時檢查代碼,而且寫起來較麻煩,當(dāng)然要達(dá)到設(shè)計目標(biāo)這個階段是必須的。大部分情況下 NQ(Native Queries)是很好的查詢接

39、口,不過遇到動態(tài)生成查詢的時候 SODA 就大有作為了。通過 SODA 查找到車牌號為“川A00000”的車主姓名。清單5:清單5package com;import javautilList;import boAutoInfo;import comdb4oDb4o;import comdb4oObjectContainer;import comdb4oqueryQuery;public class DB4OTestpublic static void main(String args)/打開數(shù)據(jù)庫ObjectContainer db = Db4oopenFile("autoyap&

40、quot;);try/構(gòu)造查詢對象Query query=dbquery();/設(shè)置被約束實(shí)例queryconstrain(AutoInfoclass);/設(shè)置被約束實(shí)例的字段和約束條件querydescend("_licensePlate")constrain("川A00000");/查詢對象List<AutoInfo> list = queryexecute(); for(int x = 0; x < listsize(); x+) Systemoutprintln("車主姓名:"+listget(x)getOw

41、nerNo()getName();finally/關(guān)閉連接dbclose();通過 API,發(fā)現(xiàn) Query 實(shí)例增加了 sortBy 按字段排序方法和 orderAscending正序、orderDescending 倒序排列方法,SODA 比 QBE 更進(jìn)了一步。NQ(Native Queries)精彩總是在最后出場,NQ 才是 db4o 查詢方式中最精彩的地方!有沒有想過用你熟悉的的編程語言進(jìn)行數(shù)據(jù)庫查詢呢?要是這樣,你的查詢代碼將是 100% 的類型安全、100% 的編譯時檢查以及 100% 的可重構(gòu),很奇妙吧?NQ 可以做到這些。有兩篇論文專門講解了 NQ 的基本概念和設(shè)計思路,分別

42、是 Cook/Rosenberger,持久對象原生數(shù)據(jù)庫查詢語言 和 Cook/Rai,Safe Query Objects: Statically Typed Objects as Remotely Executable Queries。作為結(jié)果集的一部分,NQ 表達(dá)式必須返回 true 值來標(biāo)記特定實(shí)例。如果可能的話 db4o 將嘗試優(yōu)化 NQ 表達(dá)式,并依賴索引來運(yùn)行表達(dá)式。通過 NQ 查找到車牌號為“川A00000”的車主姓名。清單6:清單6package com;import javautilList;import boAutoInfo;import comdb4oDb4o;impo

43、rt comdb4oObjectContainer;import comdb4oqueryPredicate;public class DB4OTestpublic static void main(String args)/打開數(shù)據(jù)庫ObjectContainer db = Db4oopenFile("autoyap");tryList <AutoInfo> list = dbquery(new Predicate<AutoInfo>() public boolean match(AutoInfo ai) /這樣才是類型安全的 return aig

44、etLicensePlate()equals("川A00000"); ); for(int x = 0; x < listsize(); x+) Systemoutprintln(listget(x)getOwnerNo()getName();finally/關(guān)閉連接dbclose();必須指出 NQ 的一個的問題是:在內(nèi)部,db4o 設(shè)法把 NQ 轉(zhuǎn)換成 SODA。但并不是所有的查詢表達(dá)式都可以成功轉(zhuǎn)換。有些查詢表達(dá)式的流向圖(flowgraph)非常難于分析。這種情況下,db4o 將不得不實(shí)例化一些持久對象來真實(shí)地運(yùn)行 NQ 表達(dá)式。正在開發(fā)中的 NQ 查詢優(yōu)化器

45、就可以化解這個障礙,它將分析 NQ 表達(dá)式的每個部分,以確保最少量的實(shí)例化對象,以此提高性能。當(dāng)然,優(yōu)化器的不是靈丹妙藥,關(guān)鍵還需要自己多優(yōu)化代碼。開發(fā) Java EE 項(xiàng)目經(jīng)常會用到分頁,怎樣用 NQ 實(shí)現(xiàn)呢?向數(shù)據(jù)庫寫入六條記錄。清單7:清單7package com;import javautilList;import boAutoInfo;import comdb4oDb4o;import comdb4oObjectContainer;import comdb4oqueryPredicate;public class DB4OTestpublic static void main(Str

46、ing args)/打開數(shù)據(jù)庫ObjectContainer db = Db4oopenFile("autoyap");tryList<AutoInfo> list = dbquery(new Predicate<AutoInfo>() public boolean match(AutoInfo ai) return true; );/記錄總數(shù)Integer count = listsize();/每頁兩條,分三頁 for(int x = 0; x < 3; x+) Systemoutprintln("第"+x+"

47、頁:"+listget(x*2)getLicensePlate(); Systemoutprintln("第"+x+"頁:"+listget(x*2+1)getLicensePlate();finally/關(guān)閉連接dbclose();我們發(fā)現(xiàn),在進(jìn)行 NQ 查詢時并沒有加入任何條件(無條件返回 true),是不是相當(dāng)于遍歷了整個數(shù)據(jù)庫?db4o 的設(shè)計者早就想到了這個問題,當(dāng) dbquery() 執(zhí)行完畢返回 list 實(shí)例的時候,db4o 只是與數(shù)據(jù)庫同步取出內(nèi)部 IDs 而已,并沒有把所有的 AutoInfo 對象全部取出,只有在 list

48、get(x*2)getLicensePlate() 之后才會去根據(jù) IDs 取出記錄。所以不必?fù)?dān)心性能問題。結(jié)論db4o 為開發(fā)者提供了多種查詢方式,這些方式都很靈活。要引起大家注意的是:靈活在帶來便利的同時也對開發(fā)者自身素質(zhì)提出了更高的要求,(比如排序,既可以用 SODA 也可以用 Java 集合對象實(shí)現(xiàn))在開發(fā)過程中一定要形成某種統(tǒng)一的開發(fā)模式,這樣 db4o 才能最高效能地為我所用。第 3 部分: 深入db4oRosen Jiang, 軟件工程師, db4o 和 OO 的忠實(shí) fansRosen Jiang 來自成都,是 db4o 和 OO 的忠實(shí) fans,是 2005 年 db4o

49、的 dvp 獲得者之一。他正在 J2me 應(yīng)用中使用 db4o,你可以通過 rosener_722 和他聯(lián)系。Chris (chrisMatrixorgcn), Matrix 創(chuàng)辦者, MatrixChris 來自香港,熱愛開源和 db4o。他創(chuàng)辦了中國最火熱的 Java 和開源社區(qū) Matrix(http:/www.M), 你可以通過 chrisM 和他聯(lián)系。張 黃矚 (zhanghuangzhugmailcom), 軟件工程師, 熱愛開源軟件張黃矚,熱愛開源軟件,熟悉 Java/C/C+ 編程語言,對數(shù)據(jù)庫技術(shù)網(wǎng)絡(luò)技術(shù)均感興趣。你可以通過 zhanghuangzhu 聯(lián)系他。簡介:

50、0;這篇文章是開源面向?qū)ο髷?shù)據(jù)庫 db4o 之旅 系列文章的第 3 部分,介紹面向?qū)ο髷?shù)據(jù)庫 db4o 的修改和刪除,并對其中出現(xiàn)的問題進(jìn)行細(xì)致分析,引入了“更新深度(update depth)”這一重要概念。前言在開源面向?qū)ο髷?shù)據(jù)庫 db4o 之旅 系列文章的第 1 部分:初識 db4o 中,作者介紹了 db4o 的歷史和現(xiàn)狀,應(yīng)用領(lǐng)域,以及和 ORM 等的比較; 在第 2 部分:db4o 查詢方式中, 作者介紹了 db4o 的三種不同的查詢方式:QBE、SODA 以及 Native Queries,并分別通過這三種不同的途徑實(shí)現(xiàn)了兩個關(guān)聯(lián)對象的查詢。前面我們已經(jīng)介紹了如何在 db4o 中查

51、詢以及添加對象,在本文中我們將會向您介紹在 db4o 中如何對對象進(jìn)行更新以及刪除操作。更新數(shù)據(jù)場景一 我們來設(shè)想這樣的場景:一位名叫“張三”的人買了車,并上好了牌照(如本系列第二部分之代碼),而他基本信息的地址并不詳細(xì),只寫了“成都市”,在一次主管部門檢查此人信息的時候,發(fā)現(xiàn)了這個問題,并立即著手修改。在 db4o 中,我們這樣來實(shí)現(xiàn)對這個用戶信息的修改(清單1):清單1 修改地址package com;import boPeople;import comdb4oDb4o;import comdb4oObjectContainer;import comdb4oObjectSet;import

52、 comdb4oqueryPredicate;public class DB4OTestpublic static void main(String args)/打開數(shù)據(jù)庫ObjectContainer db = Db4oopenFile("autoyap");tryObjectSet<People> result = dbquery(new Predicate<People>() public boolean match(People people) return peoplegetName()equals("張三"); );P

53、eople people = resultnext();/修改地址peoplesetAddress("成都市金牛區(qū)xxx號");dbset(people);finally/關(guān)閉連接dbclose();修改數(shù)據(jù)是如此的簡單,通過 NQ 查詢出 People 對象,接著修改其地址,最后保存即可?,F(xiàn)在我們來看看修改是否成功, 打開 ObjectManager ,如圖 1 所示,我們可以看到數(shù)據(jù)庫里的用戶數(shù)據(jù)已經(jīng)更新了。圖1 修改地址與本系列文章第二部分不同的是,我們利用 ObjectSet<People> result 來獲取返回結(jié)果,而不是 List<Peop

54、le> list。查閱 ObjectSet 的 API 我們發(fā)現(xiàn) ObjectSet 實(shí)際上繼承了 javautilList 和 javautilIterator。為什么要繼承兩個接口?這是由于 db4o 為了方便開發(fā)者而有意這樣設(shè)計的,db4o 的設(shè)計目標(biāo)就是輕量級,這樣的繼承方式為 ObjectSet 提供了多種特性,而無需開發(fā)者在多個集合接口之間轉(zhuǎn)換。場景二 讓我們考慮下面這個場景:由于工作原因,“張三”要離開省會去其他城市發(fā)展,他的汽車也要在那里使用,為了方便,他還是決定重新更換為本地牌照。 這次我們幾乎和場景一采用同樣的代碼,但結(jié)果卻不同(清單2):清單2 修改地址和車牌(不成

55、功)package com;import boPeople;import comdb4oDb4o;import comdb4oObjectContainer;import comdb4oObjectSet;import comdb4oqueryPredicate;public class DB4OTestpublic static void main(String args)/打開數(shù)據(jù)庫ObjectContainer db = Db4oopenFile("autoyap");tryObjectSet<People> result = dbquery(new Predicate<People>() public bool

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論