前言html
在開源面向對象數據庫 db4o 之旅 系列文章的第 1 部分:初識 db4o 中,做者介紹了 db4o 的歷史和現狀,應用領域,以及和 ORM 等的比較; 在第 2 部分:db4o 查詢方式中, 做者介紹了 db4o 的三種不一樣的查詢方式:QBE、SODA 以及 Native Queries,並分別經過這三種不一樣的途徑實現了兩個關聯對象的查詢。java
前面咱們已經介紹瞭如何在 db4o 中查詢以及添加對象,在本文中咱們將會向您介紹在 db4o 中如何對對象進行更新以及刪除操做。數據庫
更新數據編程
場景一網絡
咱們來設想這樣的場景:一位名叫「張三」的人買了車,並上好了牌照(如本系列第二部分之代碼),而他基本信息的地址並不詳細,只寫了「成都市」,在一次主管部門檢查此人信息的時候,發現了這個問題,並當即着手修改。jsp
在 db4o 中,咱們這樣來實現對這個用戶信息的修改(清單1):
清單1. 修改地址編程語言
-
-
package com;
-
-
import bo.People;
-
-
import com.db4o.Db4o;
-
import com.db4o.ObjectContainer;
-
import com.db4o.ObjectSet;
-
import com.db4o.query.Predicate;
-
-
public
class DB4OTest
{
-
-
public
static
void main
(
String
[
] args
)
{
-
//打開數據庫
-
ObjectContainer db = Db4o.
openFile
(
"auto.yap"
);
-
try
{
-
ObjectSet<People> result = db.
query
(
new Predicate<People>
(
)
{
-
public
boolean match
(People people
)
{
-
return people.
getName
(
).
equals
(
"張三"
);
-
}
-
}
);
-
People people = result.
next
(
);
-
//修改地址
-
people.
setAddress
(
"成都市金牛區xxx號"
);
-
db.
set
(people
);
-
}
finally
{
-
//關閉鏈接
-
db.
close
(
);
-
}
-
}
-
}
修改數據是如此的簡單,經過 NQ 查詢出 People 對象,接着修改其地址,最後保存便可。如今咱們來看看修改是否成功, 打開 ObjectManager ,如圖 1 所示,咱們能夠看到數據庫裏的用戶數據已經更新了。
圖1. 修改地址
性能
與本系列文章第二部分不一樣的是,咱們利用 ObjectSet<People> result 來獲取返回結果,而不是 List<People> list。查閱 ObjectSet 的 API 咱們發現 ObjectSet 實際上繼承了 java.util.List 和 java.util.Iterator。爲何要繼承兩個接口?這是因爲 db4o 爲了方便開發者而有意這樣設計的,db4o 的設計目標就是輕量級,這樣的繼承方式爲 ObjectSet 提供了多種特性,而無需開發者在多個集合接口之間轉換。學習
場景二網站
讓咱們考慮下面這個場景:
因爲工做緣由,「張三」要離開省會去其餘城市發展,他的汽車也要在那裏使用,爲了方便,他仍是決定從新更換爲本地牌照。
此次咱們幾乎和場景一採用一樣的代碼,但結果卻不一樣(清單2):
清單2. 修改地址和車牌(不成功)
-
-
package com;
-
-
import bo.People;
-
-
import com.db4o.Db4o;
-
import com.db4o.ObjectContainer;
-
import com.db4o.ObjectSet;
-
import com.db4o.query.Predicate;
-
-
public
class DB4OTest
{
-
-
public
static
void main
(
String
[
] args
)
{
-
//打開數據庫
-
ObjectContainer db = Db4o.
openFile
(
"auto.yap"
);
-
try
{
-
ObjectSet<People> result = db.
query
(
new Predicate<People>
(
)
{
-
public
boolean match
(People people
)
{
-
return people.
getName
(
).
equals
(
"張三"
);
-
}
-
}
);
-
People people = result.
next
(
);
-
//修改地址
-
people.
setAddress
(
"綿陽市xx區xxx號"
);
-
//修改車牌號
-
people.
getAutoInfoList
(
).
get
(
0
).
setLicensePlate
(
"川B00000"
);
-
db.
set
(people
);
-
}
finally
{
-
//關閉鏈接
-
db.
close
(
);
-
}
-
}
-
}
想必應該保存成功了吧,只是多加入了設置車牌的代碼。打開 ObjectManager,如圖 2 所示。很奇怪,地址保存成功了,而車牌卻根本沒變化。
圖2. 修改地址和車牌(不成功)
其實這也是 db4o 的有意安排。設想一個複雜對象有不少成員,而且這些成員又有本身的成員。當更新該對象,db4o 將不得不更新其全部的關聯對象、關聯對象的關聯對象,等等。這將引發嚴重的性能懲罰,並且在大部分的狀況下是沒有必要這樣的。
db4o 引入了「更新深度(update depth)」這一律念來控制被更新的對象成員樹深度。默認的更新深度是 1,這就意味着只有基本類型和 String 類型的成員變量能夠被更新,而修改對象成員將得不到任何反映,例如本例中修改 People 對象的 _autoInfoList 成員。
爲了能更新成員對象,ob4o 提供了 cascadeOnUpdate() 方法,該方法必須在每次開啓數據庫以前設置清單3:
清單3. 修改地址和車牌(成功)
-
-
package com;
-
-
import bo.People;
-
-
import com.db4o.Db4o;
-
import com.db4o.ObjectContainer;
-
import com.db4o.ObjectSet;
-
import com.db4o.query.Predicate;
-
-
public
class DB4OTest
{
-
-
public
static
void main
(
String
[
] args
)
{
-
//級聯設置
-
Db4o.
configure
(
).
objectClass
(
"bo.People"
)
-
.
cascadeOnUpdate
(
true
);
-
//打開數據庫
-
ObjectContainer db = Db4o.
openFile
(
"auto.yap"
);
-
try
{
-
ObjectSet<People> result = db.
query
(
new Predicate<People>
(
)
{
-
public
boolean match
(People people
)
{
-
return people.
getName
(
).
equals
(
"張三"
);
-
}
-
}
);
-
People people = result.
next
(
);
-
//修改地址
-
people.
setAddress
(
"綿陽市xx區xxx號"
);
-
//修改車牌號
-
people.
getAutoInfoList
(
).
get
(
0
).
setLicensePlate
(
"川B00000"
);
-
db.
set
(people
);
-
}
finally
{
-
//關閉鏈接
-
db.
close
(
);
-
}
-
}
-
}
這下終於如願以償,如圖 3 所示。其實 db4o 爲開發者想得很周到,關鍵是如何用好這些特性。
圖3. 修改地址和車牌(成功)
刪除數據
場景三
「張三」換了工做後,事業發展很快,準備把車賣了換新的,因而他去交管部門辦理移交手續,刪除關聯的車輛信息清單4:
清單4. 刪除車輛
-
-
package com;
-
-
import bo.AutoInfo;
-
-
import com.db4o.Db4o;
-
import com.db4o.ObjectContainer;
-
import com.db4o.ObjectSet;
-
import com.db4o.query.Predicate;
-
-
public
class DB4OTest
{
-
-
public
static
void main
(
String
[
] args
)
{
-
//打開數據庫
-
ObjectContainer db = Db4o.
openFile
(
"auto.yap"
);
-
try
{
-
ObjectSet<AutoInfo> result = db.
query
(
new Predicate<AutoInfo>
(
)
{
-
public
boolean match
(AutoInfo ai
)
{
-
//匹配姓名和車牌號
-
return ai.
getLicensePlate
(
).
equals
(
"川B00000"
)
-
&& ai.
getOwnerNo
(
).
getName
(
).
equals
(
"張三"
);
-
}
-
}
);
-
AutoInfo ai = result.
next
(
);
-
//刪除車輛信息
-
db.
delete
(ai
);
-
}
finally
{
-
//關閉鏈接
-
db.
close
(
);
-
}
-
}
-
}
如圖 4 所示,所關聯的車輛信息已被刪除了。
圖4. 刪除車輛信息
場景四
在場景三的基礎上修改一下,設想「張三」因爲工做不順,致使最後維護汽車的開支都困難,他不得不退出有車一族的行列清單5:
清單5. 刪除全部信息
-
-
package com;
-
-
import bo.People;
-
-
import com.db4o.Db4o;
-
import com.db4o.ObjectContainer;
-
import com.db4o.ObjectSet;
-
import com.db4o.query.Predicate;
-
-
public
class DB4OTest
{
-
-
public
static
void main
(
String
[
] args
)
{
-
//級聯設置
-
Db4o.
configure
(
).
objectClass
(
"bo.People"
)
-
.
cascadeOnDelete
(
true
);
-
//打開數據庫
-
ObjectContainer db = Db4o.
openFile
(
"auto.yap"
);
-
try
{
-
ObjectSet<People> result = db.
query
(
new Predicate<People>
(
)
{
-
public
boolean match
(People people
)
{
-
//匹配姓名
-
return people.
getName
(
).
equals
(
"張三"
);
-
}
-
}
);
-
People people = result.
next
(
);
-
//刪除車主以及關聯的車輛信息
-
db.
delete
(people
);
-
}
finally
{
-
//關閉鏈接
-
db.
close
(
);
-
}
-
}
-
}
用過 Hibernate 的開發者都知道,它的級聯刪除讓人留下了深入印象,第一次使用的時候都會爲之振奮。db4o 也爲開發者提供了級聯刪除,和場景二的級聯更新同樣, cascadeOnDelete() 是專門爲刪除準備的,基本概念和 cascadeOnUpdate() 一致。打開 ObjectManager 咱們會發現數據庫已經清空了,張三的購車經歷到此結束。
結論
經過本系列文章,db4o 的優點已經體現得淋漓盡致,它的添加、更新、刪除是如此的簡單,正如 db4o 的口號那樣——「僅需一行代碼就能存儲複雜結構對象,極大的下降了開發時間和成本,提供高效的性能,無需 DBA 干預」。
如本文有不詳盡之處,你們能夠參考官方的《用戶指南》或訪問 db4o 官方中文論壇,db4o 中文社區正在火熱成長!
參考資料
學習
得到產品和技術
討論
做者簡介
|
Rosen Jiang 來自成都,是 db4o 和 OO 的忠實 fans,是 2005 年 db4o 的 dvp 得到者之一。他正在 J2me 應用中使用 db4o,你能夠經過 rosener_722@hotmail.com 和他聯繫。 |
|
Chris 來自香港,熱愛開源和 db4o。他創辦了中國最火熱的 Java 和開源社區 Matrix(http://www.Matrix.org.cn), 你能夠經過 chris@Matrix.org.cn 和他聯繫。 |