摘要:介紹了開源的,面向?qū)ο髷?shù)據(jù)庫db4o的優(yōu)點(diǎn)及特性,通過c#語言展示其如何在程序設(shè)計(jì)中使用和操作。細(xì)致講解db4o如何對(duì)數(shù)據(jù)庫中的對(duì)象進(jìn)行基本的加載,更新,刪除操作及其三種十分重要的查詢方式。
關(guān)鍵詞:面向?qū)ο髷?shù)據(jù)庫,db4o,開源,程序設(shè)計(jì)
1引言
面向?qū)ο笫且环N認(rèn)識(shí)方法學(xué),也是一種新的程序設(shè)計(jì)方法學(xué)。把面向?qū)ο蟮姆椒ê蛿?shù)據(jù)庫技術(shù)結(jié)合起來可以使數(shù)據(jù)庫系統(tǒng)的分析、設(shè)計(jì)最大程度地與人們對(duì)客觀世界的認(rèn)識(shí)相一致。面向?qū)ο髷?shù)據(jù)庫系統(tǒng)是為了滿足新的數(shù)據(jù)庫應(yīng)用需要而產(chǎn)生的新一代數(shù)據(jù)庫系統(tǒng)。
這里要介紹的db4o數(shù)據(jù)庫就是一種Java,.NET及Mono原生的性能卓越的純面向?qū)ο蟮拈_源的數(shù)據(jù)庫引擎,由來自加州硅谷的開源面向?qū)ο髷?shù)據(jù)庫公司db4objects開發(fā)研制。對(duì)于Java與.NET開發(fā)者來說都是一個(gè)簡單易用的對(duì)象持久化工具,使用簡單,你只需要在你的項(xiàng)目中加入db4o.dll的引用即可。目前一些世界級(jí)的領(lǐng)導(dǎo)廠商如Inter,IBM,Bosch,BMW,Seagate,Hertz等都是它的客戶。
b4o的目標(biāo)是提供一個(gè)適合嵌入的功能強(qiáng)大的數(shù)據(jù)庫引擎,用以工作在移動(dòng)設(shè)備,桌面以及服務(wù)器等各種平臺(tái)。其主要特性如下:
開源模式:與其他ODBMS不同,db4o為開源軟件。
原生數(shù)據(jù)庫:db4o是100%的原生的面向?qū)ο髷?shù)據(jù)庫,直接使用編程語言來操作數(shù)據(jù)庫。程序員無需進(jìn)行OR映射來存儲(chǔ)對(duì)象,大大節(jié)省了程序員在存儲(chǔ)數(shù)據(jù)的開發(fā)時(shí)間。
高性能:db4o安裝簡單占空間小,僅需要400Kb左右。在db4o官方公布的基準(zhǔn)測試數(shù)據(jù)中,db4o比采用Hibernate/MySQL方案在某些測試線路上速度高出44倍之多。
零管理:使用db4o無需DBA。
db4o支持Java和.Net平臺(tái)。
2設(shè)計(jì)類實(shí)例
在對(duì)db4o數(shù)據(jù)庫的特點(diǎn)和特性有了大致了解后,我們通過一個(gè)例子來介紹db4o數(shù)據(jù)庫在程序設(shè)計(jì)中的使用。事例語言為C#語言,這個(gè)例子展示如何存儲(chǔ)、更新、加載、刪除一個(gè)只包括系統(tǒng)內(nèi)置類型及字符串成員的簡單對(duì)象實(shí)例,這個(gè)對(duì)象是一個(gè)存儲(chǔ)了學(xué)生(Student)的相關(guān)信息如姓名及本學(xué)期所取得學(xué)分的類。
publicclassStudent
{privatestring_name;
privateint_points;
publicStudent(stringname,intpoint)
{_name=name;
_points=points;}
publicstringname
{get{return_name;}
set{_name=value;}}
publicintpoints
{get{return_points;}
set{_points=value;}}
publicvoidAddPoints(intpoints)
{points+=points;}
overridepublicstringToString()
{returnstring.Format("{0}/{1}",_name,_points);}}
3打開關(guān)閉數(shù)據(jù)庫
使用Db4o.OpenFile()函數(shù)打開或新建一個(gè)db4o數(shù)據(jù)庫,Db4o.OpenFile()需要一個(gè)參數(shù)作為特定路徑的文件名,以此來獲得特定的ObjectContainer實(shí)例——ObjectContainer對(duì)外就是一個(gè)數(shù)據(jù)庫,也是我們操作db4o的主要接口。關(guān)閉ObjectContainer使用Close()函數(shù),它將會(huì)關(guān)閉數(shù)據(jù)庫文件并釋放其占用的系統(tǒng)資源。
ObjectContainerdb=Db4o.OpenFile(FilePathName);
try
{//Youcandosomethinghere}
finally
{db.Close();}
此處db作為下文引用和存儲(chǔ)數(shù)據(jù)庫文件的變量名,其打開和關(guān)閉數(shù)據(jù)庫的操作后面將不再寫出。
4保存對(duì)象
當(dāng)我們想保存一個(gè)對(duì)象時(shí),我們只需要簡單的調(diào)用db4o的Set()方法,并傳入要保存的對(duì)象作為參數(shù)即可。比如向db4o數(shù)據(jù)庫存入一個(gè)姓名為“Liming”,學(xué)分是86的學(xué)生對(duì)象。代碼如下:
Studentstu=newStudent("Liming",86);
db.Set(stu);
Console.WriteLine("Student{0}",stu.Tostring());
5加載對(duì)象
db4o提供了三種不同的查詢數(shù)據(jù)的方法,(1)QBE:通過實(shí)例查詢;(2)NQ:db4o原生/本地化查詢;(3)SODA:一種通過數(shù)據(jù)庫持久層進(jìn)行的查詢,查詢語句被定義在字符串中,并通過持久引擎進(jìn)行解釋執(zhí)行。其中NQ是db4o推薦使用的查詢方式。這是因?yàn)镹Q方式提供了非常強(qiáng)大的查詢功能,支持原生語言,也就意味著你可以使用Java,.net來判斷該對(duì)象是否符合條件,這是其他數(shù)據(jù)庫查詢語言無法比擬的。在某些情況下,db4o核心會(huì)將NQ翻譯成SODA以獲得更高的性能。
這下面分別詳細(xì)介紹一下這三種查詢語言。
5.1QBE查詢
當(dāng)使用QBE進(jìn)行查詢時(shí),我們需要為希望加載的數(shù)據(jù)而創(chuàng)建一個(gè)對(duì)象原型(prototypical),db4o將會(huì)加載所有與原型相同類型(各成員字段不為默認(rèn)值)的對(duì)象,返回的結(jié)果將會(huì)存儲(chǔ)在ObjectSet對(duì)象實(shí)例中。
這如果想要從數(shù)據(jù)庫中加載所有的學(xué)生對(duì)象,我們要提供了一個(gè)初始值為空的Student原型對(duì)象。原型對(duì)象中車手的積分為0,這是因?yàn)閷?duì)于int型字段的默認(rèn)值為0。
Studentstu=newStudent(null,0);
ObjectSetresult=db.Get(stu);
foreach(objectiteminresult)
{Console.WriteLine("Student{0}",stu.Tostring());}
如果我們想要從數(shù)據(jù)庫中加載特定的學(xué)生對(duì)象,只需要相應(yīng)提供給數(shù)據(jù)庫你所需要的信息即可。比如想得到姓名為“Liming”,學(xué)分值是80的學(xué)生對(duì)象:
Studentstu=newStudent("Liming",80);
ObjectSetresult=db.Get(stu);
foreach(objectiteminresult)
{Console.WriteLine("Student{0}",stu.Tostring());}
通過上面的例子我們不難看出,使用QBE方式進(jìn)行查詢存在著如下幾個(gè)局限點(diǎn):
1)db4o需要反射你提供模板對(duì)象的所有成員數(shù)據(jù);
2)不能使用高級(jí)查詢表達(dá)式,如AND、OR、NOT等;
3)對(duì)于數(shù)據(jù)不能使用強(qiáng)制條件,如int的0,string的空字串或空引用類型,因?yàn)樗鼈冊(cè)诓樵儠r(shí)都解釋為非強(qiáng)制關(guān)系;
需要為類提供非初始化成員數(shù)據(jù)的構(gòu)造函數(shù),這意味著在定義數(shù)據(jù)成員時(shí)不能對(duì)其進(jìn)行初始化。
所以,我們推薦的是另一種查詢方式NQ。
5.2NQ查詢
使用NQ為你的查詢提供了開發(fā)語言內(nèi)置的支持能力,提供類型安全機(jī)制、編譯時(shí)檢查及反射功能,使用面向?qū)ο蟮姆椒ㄕ{(diào)用來完成查詢。NQ是db4o數(shù)據(jù)庫查詢的主要接口也是開發(fā)者極力推薦的數(shù)據(jù)查詢方式,因?yàn)镹Q充分運(yùn)用了開發(fā)語言的語義完整性,將會(huì)成為將來完美而安全的選擇。
這也有人說使用NQ查詢就是用你熟悉的編程語言進(jìn)行數(shù)據(jù)庫查詢。所以這樣寫出的查詢代碼將是100%的類型安全、100%的編譯時(shí)檢查以及100%的可重構(gòu)。
下面我們看看在C#語言中NQ是如何進(jìn)行使用的。
C#.NET2.0
Iliststu=db.Query(delegate(Studentstu){
returnStu.points=80;});
C#.NET1.1
IListlist=db.query(newStudentPoints());
publicclassStudentPoints:Predicate{
{publicbooleanmatch(Studentstu)
{returnstu.Points=80;}};
for(intx=0;x
{Console.Writeline(list.get(x));}
從上述代碼中可以看出,對(duì)于不支持泛型的語言來說,都需要提供一個(gè)擴(kuò)展com.db4o.Predicate的類,并提供一個(gè)參數(shù)為待查詢的類,并返回布爾值的函數(shù)#.Match()或#.match(),其函數(shù)簽名為:
boolMatch(Pilotcandidate);
可以看到,在進(jìn)行NQ查詢時(shí)并沒有加入任何條件(無條件返回true),那么這么做是不是相當(dāng)于遍歷了整個(gè)數(shù)據(jù)庫?db4o的設(shè)計(jì)者早就想到了這個(gè)問題,當(dāng)db.query()執(zhí)行完畢返回list實(shí)例的時(shí)候,db4o只是與數(shù)據(jù)庫同步取出內(nèi)部的IDs而已,并沒有把所有的Student對(duì)象全部取出,只有在list.get(x)之后才會(huì)去根據(jù)IDs取出記錄。所以我們不必?fù)?dān)心性能方面的問題。
5.3SODA查詢
SODA是db4o提供的底層查詢接口,允許開發(fā)人員直接操作查詢表達(dá)式樹中的節(jié)點(diǎn),它采用字符串標(biāo)識(shí)對(duì)象數(shù)據(jù)成員,但是這種方式既不是類型安全也不在編譯時(shí)進(jìn)行檢查并且寫起來十分冗長。
比如我們想查找成績?cè)?0到90分之間,或者姓名為“Liming”的對(duì)象。用NQ查詢代碼如下:
IListresult=db.Query(delegate(Studentstu){
returnstu.Points>80
&&stu.Points<90
||stu.Name=="Liming";});
而用SODA寫起來則較麻煩一些:
Queryquery=db.Query();
query.Constrain(typeof(Student));
QuerypointQuery=query.Descend("_points");
query.Descend("_name").Constrain("Liming")
.Or(pointQuery.Constrain(80).Greater()
.And(pointQuery.Constrain(90).Smaller()));
ObjectSetresult=query.Execute();而SODA也有其它兩種查詢不可比擬的優(yōu)勢,那就是使你的應(yīng)用程序能夠動(dòng)態(tài)生成查詢,這種情況也是我們?cè)趹?yīng)用開發(fā)中所需要的。
看一看由QBE查詢轉(zhuǎn)換為SODA的例子,想得到所有車手的對(duì)象信息,對(duì)于查詢的約束為Student類對(duì)象。
Queryquery=db.Query();
query.Constrain(typeof(Student));
ObjectSetresult=query.Execute();
ListResult(result);
為了通過學(xué)生姓名字進(jìn)行查詢,我們需要擴(kuò)展上述約束條使其包含待查詢對(duì)象的”name”字段的相應(yīng)字符串。
Queryquery=db.Query();
query.Constrain(typeof(Student));
query.Descend("_name").Constrain("Liming");
ObjectSetresult=query.Execute();
ListResult(result);
現(xiàn)在對(duì)db4o數(shù)據(jù)庫的查詢工作做一個(gè)總結(jié)。我們可以通過其提供的三種方式中的任意一種來完成。對(duì)于何時(shí)采用哪種方式進(jìn)行查詢,我們的建議是:
。1)NQ作為db4o主要的查詢接口將是我們不二的首選;
。2)當(dāng)前版本中對(duì)NQ查詢的優(yōu)化操作總是以SODA方式來執(zhí)行的,因此SODA可以作為系統(tǒng)優(yōu)化的一種途徑,同時(shí)它總是用來在運(yùn)行時(shí)動(dòng)態(tài)的生成查詢。
。3)QBE對(duì)于初學(xué)者來說將是很好的選擇,當(dāng)然它在功能上會(huì)有些限制,如果你喜歡的話有時(shí)對(duì)的應(yīng)用還是很適合的。
6更新對(duì)象
更新對(duì)象跟存儲(chǔ)它們一樣簡單,實(shí)際上我們只需要把更改后的對(duì)象在存入數(shù)據(jù)庫中就可以了。即再次調(diào)用同樣的方法Set()方法就可以了。
ObjectSetresult=db.Get(newStudent("Liming",0));
Studentstu=(Student)result.Next();
stu.AddPoints(11);
db.Set(found);
Console.WriteLine("Added11pointsfor{0}",stu.ToString());
請(qǐng)注意,在調(diào)用Set()方法更新對(duì)象之前我們先進(jìn)行了查詢,這一點(diǎn)十分重要。這是因?yàn)槿绻诋?dāng)前的存儲(chǔ)或加載操作過程所處的會(huì)話中對(duì)象對(duì)于db4o不可知的話,db4o將會(huì)向數(shù)據(jù)庫中插入一個(gè)新的對(duì)象,之所以會(huì)這樣是因?yàn)閐b4o不會(huì)自動(dòng)的去匹配先前存儲(chǔ)于數(shù)據(jù)庫的對(duì)象,而是假設(shè)你向數(shù)據(jù)庫中存入第二個(gè)擁有相同屬性的對(duì)象。
7刪除對(duì)象
刪除數(shù)據(jù)庫中的對(duì)象使用的方法是Delete()方法。
ObjectSetresult=db.Get(newStudent("Liming",0));
Studentstu=(Student)result.Next();
db.Delete(stu);
8結(jié)語
Db4o面向?qū)ο髷?shù)據(jù)庫與傳統(tǒng)數(shù)據(jù)模型相比較,優(yōu)勢體現(xiàn)在:一是Db4o對(duì)數(shù)據(jù)語義的擴(kuò)展更大,通過允許定義任何復(fù)雜的數(shù)據(jù)類型和提供與數(shù)據(jù)相關(guān)聯(lián)的行為。這種語義更接近于面向?qū)ο蟪绦蛟O(shè)計(jì)語言的語義。二是面向?qū)ο蠹夹g(shù)強(qiáng)調(diào)與數(shù)據(jù)相關(guān)的軟件的組織而不是強(qiáng)調(diào)控制流,從而把程序員的注意力轉(zhuǎn)向數(shù)據(jù)庫設(shè)計(jì)者的意圖,面向?qū)ο笳Z言和面向?qū)ο髷?shù)據(jù)庫相互形成互補(bǔ),并且又保持了各自的長處。三是Db4o在功能方面與關(guān)系數(shù)據(jù)庫有很大的區(qū)別。關(guān)系數(shù)據(jù)庫,如SQLSever在運(yùn)行時(shí)根據(jù)存在表中的數(shù)據(jù)集而導(dǎo)出一個(gè)虛結(jié)構(gòu)。Db4o數(shù)據(jù)庫本身含有對(duì)象。四是Db4o是一種主動(dòng)型數(shù)據(jù)庫,而一個(gè)關(guān)系數(shù)據(jù)庫則是被動(dòng)型的數(shù)據(jù)庫。關(guān)系數(shù)據(jù)庫主要提供的是增刪記錄的能力,而面向?qū)ο髷?shù)據(jù)庫提供了在對(duì)象中嵌入方法的能力。因而,Db4o數(shù)據(jù)庫可以嵌入很多的操作,而在關(guān)系數(shù)據(jù)庫中,這些操作需要應(yīng)用程序來實(shí)現(xiàn)。五是Db4o新引入的抽象、擴(kuò)充類型定義、用戶自定義操作以及支持版本規(guī)模型演化等概念和功能,消除了傳統(tǒng)數(shù)據(jù)庫對(duì)數(shù)據(jù)定義的一致性,提供了更為豐富的語義。
參考文獻(xiàn):
[1]Object-orienteddatabaseprogrammingwithdb4o[EB/OL].http://anf.hidotnet.com/30878/ShowPost/
[2]DB4O國內(nèi)翻譯的部分資料——Asp.NetForums[EB/OL].http://hidotnet.com/PrintThread/?PostID=30860
[3]王意潔編著.面向?qū)ο蟮臄?shù)據(jù)庫技術(shù)[M].電子工業(yè)出版社,2005
注:本文中所涉及到的圖表、注解、公式等內(nèi)容請(qǐng)以PDF格式閱讀原文。
轉(zhuǎn)載請(qǐng)注明來自:http://www.jinnzone.com/jisuanjiyingyonglw/23830.html