版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
作者:Jim Paterson;
leafy原文地址:
http://www.onjava.com/pub/a/onjava/2004/12/01/db4o.html中文地址:
http://www.matrix.org.cn/resource/article/44/44003_DB4O.html關(guān)鍵詞: DB4O Persistence Database
許多的Java程序都需要處理持久性數(shù)據(jù),在大多數(shù)的情況下,需要和關(guān)系數(shù)據(jù)庫打交道,可能是遺留數(shù)據(jù)庫或是一個(gè)工業(yè)標(biāo)準(zhǔn)的數(shù)據(jù)庫管理系統(tǒng)(DBMS)。JDBC 的API和驅(qū)動(dòng)為大多數(shù)的數(shù)據(jù)庫系統(tǒng)提供了一個(gè)使用SQL語言進(jìn)行查詢的標(biāo)準(zhǔn)方式,然而,在對(duì)象模型應(yīng)用程序和關(guān)系模型的數(shù)據(jù)庫的領(lǐng)域之間,“錯(cuò)誤匹配問題”使得接口程序十分復(fù)雜。對(duì)象模型是基于軟件工程的原理和業(yè)務(wù)領(lǐng)域的對(duì)象模型,而關(guān)系模型是基于數(shù)學(xué)原理和數(shù)據(jù)庫有效存取規(guī)則。兩種模型沒有誰比誰更好,問題是兩者是不同的,并不總能在程序中有效協(xié)調(diào)工作。
對(duì)于這個(gè)問題已經(jīng)有一些解決方案,例如Hibernate和Java Data Objects,他們?yōu)殚_發(fā)者提供了透明的持久性——應(yīng)用程序只需使用面向?qū)ο蟮腁PI處理持久性的對(duì)象,而不需要在Java代碼中嵌入SQL語句。對(duì)于EJB的容器來說,容器管理的持久性(CMP)做了類似的工作,但是對(duì)Java平臺(tái)來說這不是一個(gè)一般的持久性工具。在任何這些解決方案中,對(duì)象通過底層框架被映射關(guān)系數(shù)據(jù)庫中的表,這些底層的框架生成SQL所需要存取的對(duì)象的屬性。也就是說,對(duì)象模型越復(fù)雜,這種映射就越困難。我們所用的描述符,通常使用XML文件,來定義這種映射關(guān)系。繼承和多對(duì)多的關(guān)系,尤其是一些關(guān)系模型無法直接表示的關(guān)系增加了映射復(fù)雜度。繼承的結(jié)構(gòu)可以有不同的方式被映射到一組表中,選擇何種方式就需要在儲(chǔ)存的效率和查詢的復(fù)雜度上權(quán)衡,就如一個(gè)單獨(dú)的表要實(shí)現(xiàn)一個(gè)多對(duì)多的關(guān)系一樣。
在一個(gè)數(shù)據(jù)庫中存儲(chǔ)一個(gè)對(duì)象,數(shù)據(jù)庫本身如果就是一個(gè)對(duì)象模型,這樣,就提供了另外一個(gè)解決方案。在二十世紀(jì)九十年代,各種各樣面向?qū)ο蟮臄?shù)據(jù)庫管理系統(tǒng)被開發(fā)出來,但是這些數(shù)據(jù)庫配置十分復(fù)雜,而且需要使用對(duì)象定義語言。對(duì)象是作為對(duì)象格式存儲(chǔ)的,但是對(duì)應(yīng)用語言來說它們不是本地化的。目前這些數(shù)據(jù)庫產(chǎn)品并沒對(duì)市場(chǎng)有大的影響,只是和一些將關(guān)系和對(duì)象混雜的數(shù)據(jù)庫一樣,在關(guān)系數(shù)據(jù)庫面向?qū)ο蟮腁PI上下功夫。
嵌入式數(shù)據(jù)庫在一些應(yīng)用中,數(shù)據(jù)庫管理系統(tǒng)的維護(hù)費(fèi)用是必不可少的,在一些小功耗,可嵌入的數(shù)據(jù)庫引擎條件下,可以更好的提供數(shù)據(jù)庫的存儲(chǔ)需求,例如,SQLite,提供了一個(gè)自我包含的數(shù)據(jù)庫引擎。但是,因?yàn)檫@個(gè)JAVA的接口是通過一個(gè)JDBC驅(qū)動(dòng),這種以SQL為基礎(chǔ)的解決方案也存在“錯(cuò)誤匹配問題”。
在許多案例中,持久性問題可以變得相當(dāng)?shù)暮?jiǎn)單,如果使用嵌入式的對(duì)象數(shù)據(jù)庫引擎話。這是一個(gè)很好的機(jī)會(huì),我們來了解一下Carl Rosenberg創(chuàng)建的db4o。db4o曾經(jīng)是一個(gè)商業(yè)的對(duì)象數(shù)據(jù)庫,現(xiàn)在它是開源的,而且,最近獲得了GPL(GNU通用公共許可證)的許可證。
Db4o的功能特點(diǎn):
●????????沒有錯(cuò)誤匹配問題——對(duì)象以其本身方式來存儲(chǔ)
●????????自動(dòng)管理數(shù)據(jù)模式
●????????存儲(chǔ)時(shí)沒有改變類特征,以使得易于存儲(chǔ)
●????????與Java(.NET)無縫綁定
●????????自動(dòng)數(shù)據(jù)綁定
●????????一個(gè)250Kb的庫文件的簡(jiǎn)易安裝(Java jar or .NET DLL)
●????????一個(gè)數(shù)據(jù)庫文件
●????????自動(dòng)模式版本
●????????查詢實(shí)例
●????????S.O.D.A. (簡(jiǎn)單對(duì)象數(shù)據(jù)庫訪問), 一個(gè)開源查詢的API
Db4o的優(yōu)點(diǎn)Db4o已經(jīng)被一些嵌入式系統(tǒng)的應(yīng)用程序所選用,這些程序特點(diǎn)都是要求零管理、高可靠性和低功耗的。例如,在德國(guó),BMW Car IT在汽車嵌入式系統(tǒng)電子原型中使用了它。同樣是德國(guó)的Die Mobilanten,他們?cè)谥行凸彩聵I(yè)的PDA解決方案中使用了db4o。在美國(guó),Massie Systems為嬰兒眼睛診斷的視網(wǎng)膜圖像處理系統(tǒng)依靠db4o加強(qiáng)其客戶交流圖像數(shù)據(jù)庫。
在db4o中存儲(chǔ)對(duì)象的方式相當(dāng)?shù)暮?jiǎn)單,同時(shí),對(duì)于教學(xué)目的來說也相當(dāng)具有吸引力。艾塞克斯(英)大學(xué)和德州農(nóng)工大學(xué)都把db4o作為教學(xué)和研究對(duì)象。在我自己的學(xué)院,對(duì)于那些需要如何要將面向?qū)ο蟮母拍顟?yīng)用到他們的項(xiàng)目中去的學(xué)生,和關(guān)系數(shù)據(jù)庫打交道對(duì)于他們?cè)O(shè)計(jì)自己領(lǐng)域內(nèi)的模型來說是一個(gè)負(fù)面的影響。使用db4o可以使得他們只需和持久層的數(shù)據(jù)打交道而不需要分心處理一個(gè)相沖突的不理解的數(shù)據(jù)關(guān)系模型,也不需要花費(fèi)更多的時(shí)間學(xué)習(xí)一個(gè)工具,如Hibernate或一個(gè)復(fù)雜的OODBMS。同時(shí),學(xué)習(xí)面向?qū)ο蟛樵傾PI的概念可能在將來被證明更有效。
同樣的API,不同的存儲(chǔ)有時(shí)候,你正好不得不使用一個(gè)關(guān)系數(shù)據(jù)庫。從一個(gè)Java開發(fā)者的觀點(diǎn)來看,透明的持久性是理想境界。如果持久性可以通過面向?qū)ο蟮腁PI實(shí)現(xiàn),那么開發(fā)者就不必要為不同的數(shù)據(jù)存儲(chǔ)來學(xué)習(xí)不同的技術(shù)。盡管db4o不是JDO兼容的(作為一個(gè)結(jié)果很容易使用),它的創(chuàng)造者的伙伴們有許多其他的開源項(xiàng)目,包括Mysql和Hibernate,它們使用單一的、一致的對(duì)象持久性的API和對(duì)象數(shù)據(jù)庫交互,包括db4o本身,一些關(guān)系數(shù)據(jù)庫或者其他存儲(chǔ)模式,例如Prevayler。如果JDO對(duì)于你來說比較重要,你可以考慮ObjectDB,它是一個(gè)JDO兼容的純對(duì)象數(shù)據(jù)庫.
一個(gè)例子這個(gè)例子演示了創(chuàng)建一個(gè)數(shù)據(jù)庫和存儲(chǔ)對(duì)象是如何簡(jiǎn)單。它同時(shí)演示了兩種查詢的方法:實(shí)例查詢和更具有彈性的S.O.D.A查詢API。整個(gè)的源代碼在文章主題資源的部分可以下載[實(shí)際上對(duì)資源這部分不是合適的下載地方]。為了可以運(yùn)行,你必須在你的路徑里添加db4o jar文件并且執(zhí)行Db4oTest.java。
在實(shí)例中有兩個(gè)類,分別代表棒球隊(duì)(Team)和成員(Player)。為了使得例子更加有趣,我們還有一個(gè)投手的類(Pitcher),Pitcher是Player的一個(gè)子類。并且添加了一個(gè)額外的數(shù)據(jù)域在Pitcher中。Team類有一個(gè)屬性,就是該team的成員(player)列表,它當(dāng)然包括Pitcher對(duì)象。Team、Player、Pitcher對(duì)象是一些簡(jiǎn)單傳統(tǒng)的Java對(duì)象,這里并沒有持久層的代碼。也不需要有唯一的關(guān)鍵字屬性,當(dāng)一個(gè)對(duì)象數(shù)據(jù)庫在自動(dòng)存儲(chǔ)對(duì)象時(shí)是需要唯一對(duì)象標(biāo)識(shí)符(OIDS)。
Player class??????????????????????????????????????????????????????????????????????
public class Player {????????????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????protected String name;????????????????????????????????????????????????????????
????protected int squadNumber;????????????????????????????????????????????????????
????protected float battingAverage;??????????????????????????????????????????????
????protected Team team;??????????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public Player(String name, int squadNumber,??????????????????????????????????
????????float battingAverage){????????????????????????????????????????????????????
????????this.name = name;????????????????????????????????????????????????????????
????????this.squadNumber = squadNumber;??????????????????????????????????????????
????????this.battingAverage = battingAverage;????????????????????????????????????
????}????????????????????????????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public void setName(String n){this.name = n;}????????????????????????????????
????public String getName(){return this.name;}????????????????????????????????????
??????????
????public void setSquadNumber(int s){this.squadNumber = s;}??????????????????????
????public int getSquadNumber(){return this.squadNumber;}????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public void setBattingAverage(final float b) {????????????????????????????????
????????this.battingAverage = b; }????????????????????????????????????????????????
????public float getBattingAverage(){????????????????????????????????????????????
????????return this.battingAverage;}??????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public void setTeam(Team t) {this.team = t;}??????????????????????????????????
????public Team getTeam() {return this.team;}????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public String toString() {????????????????????????????????????????????????????
????????return name + ":" + battingAverage;??????????????????????????????????????
????}????????????????????????????????????????????????????????????????????????????
}??
????
??????????????????????????????????????????????????????????????????????????
Pitcher class ??????????????????????????????????????????????????????????????????
public class Pitcher extends Player{??????????????????????????????????????????????????
????private int wins;????????????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public Pitcher(String name, int squadNumber,??????????????????????????????????
????????????????????float battingAverage, int wins) {????????????????????????????
????????super(name,squadNumber,battingAverage);??????????????????????????????????
????????this.wins = wins;????????????????????????????????????????????????????????
????}????????????????????????????????????????????????????????????????????????????
??????????????
????public void setWins(final int w){this.wins = w;}??????????????????????????????
????public int getWins() {return this.wins;}??????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public String toString() {????????????????????????????????????????????????????
????????return name + ":" + battingAverage + ", " + wins;????????????????????????
????}????????????????????????????????????????????????????????????????????????????
}
??
??????????????????????????????????????????????????????????????????????????????
Team class ??????????????????????????????????????????????????????????????????????
import java.util.List;????????????????????????????????????????????????????????????
import java.util.ArrayList;??????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
public class Team {??????????????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????private String name;??????????????????????????????????????????????????????????
????private String city;??????????????????????????????????????????????????????????
????private int won;??????????????????????????????????????????????????????????????
????private int lost;????????????????????????????????????????????????????????????
????private List players;????????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public Team(String name, String city,????????????????????????????????????????
????????????????int won, int lost){??????????????????????????????????????????????
????????this.name = name;????????????????????????????????????????????????????????
????????this.city = city;????????????????????????????????????????????????????????
????????this.won = won;??????????????????????????????????????????????????????????
????????this.lost = lost;????????????????????????????????????????????????????????
????????this.players = new ArrayList();??????????????????????????????????????????
????}????????????????????????????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public void addPlayer(Player p) {????????????????????????????????????????????
????????players.add(p);??????????????????????????????????????????????????????????
????}????????????????????????????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
????public void setName(String n){this.name = n;}????????????????????????????????
????public String getName(){return this.name;}????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????
????public void setStadium(String c){this.city = c;}??????????????????????????????
????public String getCity(){return this.city;}????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????
????public void setPlayers(List p){players = p;}??????????????????????????????????????
????public List getPlayers(){return players;}??????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????
????public void setWon(int w) {this.won = w;}??????????????????????????????????????
????public int getWon(){return this.won;}????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????
????public void setLost(int l) {this.lost = l;}??????????????????????????????????????????????
????public int getLost() {return this.lost;}??????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????
????public String toString() {??????????????????????????????????????????????????
????????return name;????????????????????????????????????????????????????????????????????????????????????????????
????}????????????????????????????????????????????????????????????????????????????????????????????
}
??????????????????????????????????????????????????????????????????????????????????????????
首先,我們來建立一些測(cè)試數(shù)據(jù)。
// Create Players????????????????????????????????????????????????????????????????????????????????????????????
Player p1 = new Player("Barry Bonds", 25, 0.362f);??????????????????????????????????????????????
Player p2 = new Player("Marquis Grissom", 9, 0.279f);??????????????????????????????????????????????
Player p3 = new Player("Ray Durham", 5, 0.282f);??????????????????????????????????????????????
Player p4 = new Player("Adrian Beltre", 29, 0.334f);??????????????????????????????????????????????
Player p5 = new Player("Cesar Izturis", 3, 0.288f);??????????????????????????????????????????????
Player p6 = new Player("Shawn Green", 15, 0.266f);??????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????
// Create Pitchers????????????????????????????????????????????????????????????????????????????????????????????
Player p7 = new Pitcher("Kirk Rueter",46, 0.131f, 9);??????????????????????????????????????????????
Player p8 = new Pitcher("Kazuhisa Ishii",17, 0.127f, 13);??????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????
// Create Teams????????????????????????????????????????????????????????????????????????????????????????????
Team t1 = new Team("Giants", "San Francisco", 91, 71);??????????????????????????????????????????????
Team t2 = new Team("Dodgers", "Los Angeles", 93, 69);??????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????
// Add Players to Teams??????????????????????????????????????????????????????????
t1.addPlayer(p1); p1.setTeam(t1);??????????????????????????????????????????????
t1.addPlayer(p2); p2.setTeam(t1);??????????????????????????????????????????????
t1.addPlayer(p3); p3.setTeam(t1);??????????????????????????????????????????????
t2.addPlayer(p4); p4.setTeam(t2);??????????????????????????????????????????????
t2.addPlayer(p5); p5.setTeam(t2);??????????????????????????????????????????????
t2.addPlayer(p6); p6.setTeam(t2);??????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????
// Add Pitchers to Teams??????????????????????????????????????????????????????????
t1.addPlayer(p7); p7.setTeam(t1);??????????????????????????????????????????????
t2.addPlayer(p8); p8.setTeam(t2);??????????????????????????????????????????????
存儲(chǔ)數(shù)據(jù)一個(gè)Team的對(duì)象可以用一行代碼執(zhí)行存儲(chǔ)操作:
db.set(t1);??
??????????????????????????????????????????????????????????????????
這兒,db是一個(gè)指向ObjectContainer對(duì)象的一個(gè)引用,它在打開一個(gè)新數(shù)據(jù)文件時(shí)被創(chuàng)建,如下:
ObjectContainer db = Db4o.openFile(filename);????
????????????????????????????????????????????????????????
一個(gè)db4o數(shù)據(jù)庫是一個(gè)以.yap為擴(kuò)展名的文件,其中set方法用來存儲(chǔ)一個(gè)對(duì)象。
注意這里是存儲(chǔ)了一個(gè)Team的對(duì)象,并且它包含了Player的對(duì)象。我們能夠通過取回Player對(duì)象來測(cè)試是否存儲(chǔ)了這些Player的對(duì)象。最簡(jiǎn)單的方法就是用QBE來查詢。
實(shí)例查詢的簡(jiǎn)單查詢下面的代碼列出了所有與實(shí)例對(duì)象匹配的Player對(duì)象,這里它們是唯一的。通過調(diào)用ObjectContainer的get方法,結(jié)果以O(shè)bjectSet的方式返還。
Player examplePlayer = new Player("Barry Bonds",0,0f);????????????????????????????
ObjectSet result=db.get(examplePlayer);??????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
System.out.println(result.size());????????????????????????????????????????????????
while(result.hasNext()) {????????????????????????????????????????????????????????
????System.out.println(result.next());????????????????????????????????????????????
}??
????????
??????????????????????????????????????????????????????????????????????
同時(shí),我們也可以得到所有我們預(yù)先虛構(gòu)的,創(chuàng)建并存儲(chǔ)的Player對(duì)象(所有數(shù)據(jù)域?yàn)?或者是空),如下:
Player examplePlayer = new Player(null,0,0f);????????????????????????????????????
ObjectSet result=db.get(examplePlayer);??????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????
System.out.println(result.size());????????????????????????????????????????????????
while(result.hasNext()) {????????????????????????????????????????????????????????
????System.out.println(result.next());????????????????????????????????????????????
}??
????????????????????????????????????????????????????????????????????????????????????????????????
結(jié)果如下:
8????????????????????????????????????????????????????????????????????????????????????
Kazuhisa Ishii:0.127, 13????????????????????????????????????????????????????????
Shawn Green:0.266????????????????????????????????????????????????????????????????
Cesar Izturis:0.288????????????????????????????????????????????????????????????
Adrian Beltre:0.334????????????????????????????????????????????????????????????????
Kirk Rueter:0.131, 9????????????????????????????????????????????????????????????
Ray Durham:0.282????????????????????????????????????????????????????????????????
Marquis Grissom:0.279????????????????????????????????????????????????????????????
Barry Bonds:0.362????????????????????????????????????????????????????????????????
注意:我們可以取回所有的Player類的對(duì)象,包括其子類(這里是Pitcher類)的對(duì)象,而不需要任何額外的代價(jià)。上面結(jié)果中所示的Pitcher對(duì)象它們額外的信息(wins)也同樣被取回來了。而在關(guān)系數(shù)據(jù)庫中我們必須知道如何在表中映射繼承樹,可能不得不要加一些額外的表來取回對(duì)象所有的屬性。
更新和刪除更新一個(gè)對(duì)象可以混合使用上面的方法技術(shù)。下面的代碼假定了只有一個(gè)結(jié)果匹配,并且這個(gè)匹配的對(duì)象可以上溯到Player,這樣可以保證它的屬性能得到修改。
Player examplePlayer = new Player("Shawn Green",0,0f);????????????????????????????
ObjectSet result = db.get(examplePlayer);????????????????????????????????????????
Player p = (Player) result.next();??????????????????????????????????????????????
p.setBattingAverage(0.299f);????????????????????????????????????????????????????????
db.set(p);????????
????????????????????????????????????????????????????????????????????????????
數(shù)據(jù)庫的對(duì)象也可以以同樣的方式被刪除。
Player examplePlayer = new Player("Ray Durham",0,0f);????????????????????????????
ObjectSet result = db.get(examplePlayer);????????????????????????????????????????
Player p = (Player) result.next();????????????????????????????????????????????????????????????
db.delete(p);??
??????????????????????????????????????????????????????????????????
功能更強(qiáng)的查詢在早期版本的db4o中一個(gè)主要的缺點(diǎn)就是實(shí)例查詢提供相當(dāng)有限的查詢能力。例如,你不能像這樣查詢“所有平均擊球率大于30%的隊(duì)員”。現(xiàn)在,db4o包含了S.O.D.A的API可以使得查詢的能力接近SQL。一個(gè)Query類的實(shí)例代表了含有約束條件的標(biāo)準(zhǔn)查詢圖中的一個(gè)節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)可以代表一個(gè)類,或者多個(gè)類,或者一個(gè)類屬性。
下面的代碼演示了如何執(zhí)行這樣的操作。我們定義了一個(gè)查詢圖的節(jié)點(diǎn)并且指定/限制它為Player類。這意味著查詢的返回結(jié)果為Player對(duì)象。然后,我們向下具體化這張圖,去查找一個(gè)節(jié)點(diǎn),代表屬性“平均擊球率”,限制其大于0.3。最后,執(zhí)行查詢操作,返回?cái)?shù)據(jù)庫中所有滿足條件的對(duì)象。
Query q = db.query();??????????????????????????????????????????????????????????
q.constrain(Player.class);????????????????????????????????????????????????????????????
q.descend("battingAverage").constrain(new Float(0.3f)).greater();????????????????
ObjectSet result = q.execute();??????
??
??????????????????????????????????????????????????????????????????????????
初一看,這個(gè)查詢操作很類似SQL的查詢,就如這樣:
SELECT * FROM players WHERE battingAverage > 0.3??
????????????????????????????????????
然而,Player類的設(shè)計(jì)允許在Team對(duì)象和Player之間有相互引用關(guān)系,正如測(cè)試中的數(shù)據(jù)。一個(gè)Team的對(duì)象有一個(gè)應(yīng)用指向一個(gè)序列的Player對(duì)象,同時(shí)每一個(gè)Player對(duì)象都有一個(gè)Team的引用。這就意味這查詢的結(jié)果應(yīng)該包含Player和Team的對(duì)象。演示代碼如下:
System.out.println(result.size());????????????????????????????????????????????
while(result.hasNext()) {????????????????????????????????????????????????????????
????// Print Player??????????????????????????????????????????????????????????????????????????????
????Player p = (Player) result.next();??????????????????????????????????????????
????System.out.println(p);??????????????????????????????????????????????????????????????????????????????
????// Getting Player also gets Team - print Team??????????????????????????????????????
????Team t = p.getTeam();????????????????????????????????????????????????????????
????System.out.println(t);????????????????????????????????????????????????????????
}
??????????????????????????????????????????????????????????????????????????????
輸出:
2??????????????????????????????????????????????????????????????????????????????
Adrian Beltre:0.334??????????????????????????????????????????????????????????????????????????????
Dodgers??????????????????????????????????????????????????????????????????????????????
Barry Bonds:0.362??????????????????????????????????????????????????????????????????????????????
Giants??????????????????????????????????????????????????????????????????????????????
現(xiàn)在的查詢十分類似SQL語言查詢,如下:
SELECT teams.name, players.name, players.battingAverage FROM teams,????players??????????????????????????????????????????????????????????????????????????????
????WHERE teams.teamID = players.playerID??????????????????????????????????????
AND battingAverage > 0.3????
????????????????????????????????????????????????????????????????????????
這個(gè)能正常工作是因?yàn)橄嗷ヒ藐P(guān)系已經(jīng)被設(shè)計(jì)到對(duì)象模型中。對(duì)象數(shù)據(jù)庫是具有可以導(dǎo)航性的:你只要根據(jù)預(yù)定義的關(guān)系就可以取回?cái)?shù)據(jù)。從另一方面講,關(guān)系數(shù)據(jù)庫并不能直接在表中連接。所以,這樣對(duì)于特定查詢更具有彈性的。然而,在給定對(duì)象關(guān)系中,從對(duì)象數(shù)據(jù)庫中取回對(duì)象的關(guān)系幾乎不要任何的程序代價(jià)。數(shù)據(jù)庫模型和應(yīng)用程序?qū)ο竽P褪且恢碌模圆恍枰绦騿T考慮數(shù)據(jù)的差異性。如果對(duì)象在內(nèi)存里的時(shí)候,你可以從一個(gè)給定的Player中得到它所屬的Team,你就可以在對(duì)象數(shù)據(jù)庫中做同樣事。
S.O.D.A.其他功能SQL查詢?cè)试S結(jié)果按要求排序,S.O.D.A.也可以達(dá)到同樣功效。下面是一個(gè)例子演示了取回我們開始存儲(chǔ)的Player對(duì)象,并以“平均擊球率”排序。(很顯然,這樣可以知道哪些是投手)
Query q = db.query();??????????????????????????????????????????????????????????????????????????????
q.constrain(Player.class);??????????????????????????????????????????????????????????????????????????????
q.descend("battingAverage").orderAscending();??????????????????????????????????????
??????????ObjectSet result = q.execute();????
??????????????????????????????????
結(jié)果:
7??????????????????????????????????????????????????????????????????????????????
Kazuhisa Ishii:0.127, 13??????????????????????????????????????????????????????????????????????????????
Kirk Rueter:0.131, 9??????????????????????????????????????????????????????????????????????????????
Marquis Grissom:0.279??????????????????????????????????????????????????????????????????????????????
Cesar Izturis:0.288??????????????????????????????????????????????????????????????????????????????
Shawn Green:0.299??????????????????????????????????????????????????????????????????????????????
Adrian Beltre:0.334??????????????????????????????????????????????????????????????????????????????
Barry Bonds:0.362?? ??????????????????????????????????????????????????????????????????????????
S.O.D.A.可以定義更加復(fù)雜的查詢,一旦你除去考慮關(guān)系數(shù)據(jù)庫的方式思考它,那將十分的簡(jiǎn)單。為了設(shè)置限制條件,你只需根據(jù)查詢圖導(dǎo)航,去尋找你想設(shè)置條件的類或?qū)傩浴2樵儓D概念和對(duì)象模型領(lǐng)域關(guān)系十分緊密。這些對(duì)開發(fā)者理解十分有益。另一方面,為了達(dá)到類似SQL的查詢結(jié)果,你必須考慮如何映射對(duì)象領(lǐng)域和關(guān)系數(shù)據(jù)的表格。
下面的例子演示了如何在Player類的兩個(gè)屬性上設(shè)置條件。我們將去查找這樣的隊(duì)員:他的擊球率大于0.130,而且他是一個(gè)贏過五次以上的投手。另外,我們定義了一個(gè)查詢圖節(jié)點(diǎn),限制它為Player類,然后,我們具體化這張圖去尋找一個(gè)節(jié)點(diǎn)代表屬性“平均擊球率”,使其大于0.13,這個(gè)結(jié)果是一個(gè)Constraint的對(duì)象。為了設(shè)置下一個(gè)限制條件,我們具體化去尋找節(jié)點(diǎn)代表屬性“贏”,這本身就意味著是去查找一個(gè)Pticher類對(duì)象。這個(gè)節(jié)點(diǎn)的限制條件是大于5,然后使用邏輯與——“AND”操作前一個(gè)Constraint對(duì)象。
?????? Query q = db.query();????????????????????????????????????????????????
??????????q.constrain(Player.class);????????????????????????????????????????????
??????????Constraint constr =??????????????????????????????????????????????????
??????????q.descend("battingAverage").constrain(????????????????????????????????
??????????new Float(0.13f)).greater();??????????????????????????????????????????????????????????????????
q.descend("wins").constrain(??????????????????????????????????????????????????????????????????
???????? new Integer(5)).greater().and(constr);????????????????????????????????
result = q.execute();????
??????????????????????????????????????????????????????????????
結(jié)果:
1??????????????????????????????????????????????????????????????????????????????????????????????????
Kirk Rueter:0.131, 9??????????????????????????????????????????????????????????????????
????????Giants?? ??????????????????????????????????????????????????????????????
最后一個(gè)例子演示了如何組合不同類的屬性作為查詢條件。我們將查詢滿足如下條件的隊(duì)員:他的擊球率大于0.300并且他的球隊(duì)已經(jīng)贏了92場(chǎng)以上。最簡(jiǎn)單的方式是從Player類開始,然后導(dǎo)航到Team。我們可以和前面一樣具體化去查找“平均擊球率”節(jié)點(diǎn),然后,生成一個(gè)Constraint對(duì)象。然后,具體化去查找Team的屬性的時(shí)候,這個(gè)屬性是Team的,而這個(gè)節(jié)點(diǎn)代表的是Team類,因此,我們可以再次具體化去查找一個(gè)節(jié)點(diǎn)代表“贏”的Team的贏得屬性,然后生成Constraint對(duì)象,最后,我們與前一個(gè)Constraint對(duì)象與操作即可。
Query q = db.query();??????????????????????????????????????????????????????????????????
q.constrain(Player.class);??????????????????????????????????????????????????????????????????
Constraint constr =??????????????????????????????????????????????????????????????????
????????q.descend("battingAverage").constrain(????????????????????????????????
????????new Float(0.3f)).greater();??????????????????????????????????????????????????????????????????
????????q.descend("team").descend("won").constrain(????????????????????????????????
????????new Integer(92)).smaller().and(constr);????????????????????????????????
result = q.execute();??
??????????????????????????????????????????????????????????????
結(jié)果:
1??????????????????????????????????????????????????????????????????????????????????????????????????
Barry Bonds:0.362??????????????????????????????????????????????????????????????????
????????Giants??????????????????????????????????????????????????????????????????
結(jié)論一個(gè)低功耗、可嵌入的對(duì)象數(shù)據(jù)庫提供了一個(gè)十分簡(jiǎn)單、間接的方法處理對(duì)象的持久性。Db4o現(xiàn)在是一個(gè)開源的對(duì)象數(shù)據(jù)庫。它擁有一系列很具有吸引力的特點(diǎn),同時(shí)支持Java和.Net。簡(jiǎn)單的安裝,同時(shí)在對(duì)象模型和數(shù)據(jù)模型間不存在“錯(cuò)誤匹配問題”。這些使得db4o無論在商業(yè)上還是教育上都有廣泛的應(yīng)用。