前言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 和他联系。 |