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