Db4o(精选三篇)
Db4o 篇1
数据库的发展经历了三个阶段,第一阶段是层次和网状数据库,过程化程度很高,但是普通用户难以使用。第二阶段是关系数据库,它有着坚实的数学理论基础,主要以二维表为表现形式,与面向对象数据库相比,人们习惯的将上述两种数据库统称为传统数据库。
1.1 传统数据库的不足
随着应用领域的不断扩展,传统数据库的缺陷日渐凸显,主要表现在:(1)对客观世界里的复杂对象表现乏力:采用二维表表示数据及其关系,语义表示能力弱,不能完全表示客观世界复杂对象及数据之间深层含义和内在联系。(2)数据结构很难和行为相关联:客观世界里的对象一般有两个方面的内容:组成结构和行为。传统数据库把前者能很好的保存到数据库模式中,可是对后者的支持却不够理想。(3)抗阻失配:很难和高级程序设计语言做到无缝集成:开发必须同时使用数据库语言和程序开发语言进行配合操作,才能完成任务。难以做到及时发现错误和修改错误。
1.2 面向对象数据库的优势
面向对象作为一种新的方法学,将客观世界的一切实体模型化为对象,使数据库系统的分析、设计最大程度地与人们对客观世界的认识相一致,从而提高了软件开发的效率。与传统数据库相比,面向对象数据库有如下优势:(1)支持复杂的数据结构和类型;(2)实体都通过对象来表示;(3)将对象属性和对象行为封装在对象类中;(4)特殊的继承功能;(5)支持多态、重载;(6)滞后联编;(7)系统为每一个对象在内部生产一个唯一标识符等。
1.3 Db4o数据库的优点
Db4o数据库是一种由Db4objects开发研制的,可以基于Java、.Net以及Mono原生的性能卓越的纯面向对象的开源的数据库引擎。对于Java开发者来说,只要在ClassPath中添加Db4o.jar文件即可在开发环境中应用。Db4o与其他数据库相比,有如下的优点:(1)Db4o为开源软件;(2)Db4o是原生数据库,它是纯面向对象的数据库,直接使用编程语言来操作数据库;(3)最小限度的资源消耗;(4)高输入输出性能;(5)易于实现;(6)便于移植;(7)无“抗阻失调”;(8)提供了原生查询;(9)零管理等。
2 使用实例
下面用一个例子来阐释Db4o数据库如何在程序设计中使用的。实例语言采用Java语言,展示一个如何存储、更新、加载、删除一个只包含系统内置类型及字符串成员的简单对象实例,这里的对象是一个存储了顾客(Customer)的相关信息如姓名及年龄的类。
3 打开关闭数据库
使用Db4oEmbedded.openFile()函数打开或者新建一个Db4o数据库,Db4oEmbedded.openFile()需要一个参数作为特定路径的文件名,以此来获得特定的ObjectContainer实例,它就是操作Db4o的主要接口。操作代码如下:
关闭ObjectContainer使用Close()函数,它会关闭数据库文件并释放其占用的系统资源。
4 在数据库中保存对象
保存一个对象需要调用Db4o的Store()方法,并为该方法传递要保存的对象作为参数。如下面的例子是要在数据库中保存名为“Gandhi”,年龄为79的顾客对象。代码如下:
5 对象的查询方式
Db4o提供了三种不同的查询数据的方法:(1)QBE:通过实例查询;(2)NQ:db4o原生查询;(3)SODA查询:一种通过数据库持久层进行的查询,查询语句被定义在字符串中,并通过持久引擎进行解释执行。其中NQ是Db4o推荐使用的查询方式。这是因为NQ方式提供了非常强大的查询功能,支持原生语言,也就意味着你可以使用Java来判断该对象是否符合条件,这是其他查询数据库无法比拟的。在有些情况下,Db4o将会将NQ翻译成SODA执行,以便获得更高的性能。下面将随着例子来演示一下这三种查询方式在程序开发中是如何操作的。
5.1 QBE查询
当使用QBE查询时,需要为希望查询的数据创建一个对象模板,Db4o将会加载所有与模板类型相同而字段属性各异的所有对象,返回的结果存储在ObjectSet对象实例中。代码如下:ObjectSet result=(ObjectSet)db.queryByExample(new Customer());
特别值得指出的是:使用QBE方式查询是不支持高级查询表达式的,如AND和OR等。
5.2 NQ查询
使用NQ查询时,可以在程序开发的同时使用开发平台(如java)的语言对数据库进行查询,如果任何类中的字段或者类型无效的话,编译器将会给出错误提示信息,所以由这类问题导致的错误不会出现在程序的运行过程中。正因为如此,原生查询被称为安全查询。使用原生查询进行查询,代码如下:
5.3 SODA查询
SODA的基本思想是建立一个查询图,该图可以被用来表达查询。由于这些图能很容易被程序分析或者遍历,所以能非常快速的得到查询结果。因为原生查询总是通过转换成(优化或不被优化)成SODA图实现。所以SODA是原生查询的基础。
6 更新对象
更新对象是指把对象更新后的值再次存入数据库中。程序代码如下所示:
更新对象时,一定要事先用查询进行检索,找到要更新的对象,然后才能更新,否则执行上述更新代码,数据库中将会插入一个新的对象,而不是对数据库中的对象进行更新。
7 删除对象
Db4o数据库中是调用Delete方法来删除对象。具体执行代码如下:
8 结束语
Db4o面向对象数据库以其支持更加复杂的数据类型、更简易的操作、更为简单安全的数据查询方式、避免了在数据库中保存数据时所产生的抗阻失配等缺点,逐步赢得企业和开发者们的支持。相信Db4o未来的应用领域将得到进一步的扩展。
参考文献
[1]王意洁.面向对象的数据库技术[M].北京:电子工业出版社,2005.
[2]王功明,关永,赵春江.面向对象数据库的关键技术研究[J].微计算机信息,2006(3).
Db4o 篇2
在 db4o 之旅 系列文章的第一部分:初识 db4o 中,作者介绍了 db4o 的历 史和现状,应用领域,以及和 ORM 等的比较,在这篇文章中,作者将会介绍 db4o 的安装、启动以及三种不同的查询方式:QBE(Query by Example)、SODA (Simple Object Database Access) 以及 NQ(Native Queries),并分别通 过这三种不同的途径实现了两个关联对象的查询。本文还示范了开发中最经常用 到的几个典型功能的 db4o 实现。
下载和安装 db4o
db4o 所有最新的版本都可以直接在 上下载,进入 db4o 的下载页面 ,我们可以看到最新的 for Java 稳定版本是 5.5,包括 JAR、源代码、入门文 档、API 等内容的完整的打包文件只有 6 MB,db4o 还有一个对象数据库管理工 具 ObjectManager,目前版本是 1.8。
接着在 Eclipse 中新建 Java 项目,把 db4o 对象数据库引擎包 db4o-5.5 -java5.jar 导入进项目。由于 db4o 支持多种版本的 JDK,除了 for JDK 5.0 的 db4o-5.5-java5.jar 外,还有 for JDK 1.1、1.2-1.4 的 JAR 包,以适应 多种环境。与 Hibernate、iBATIS SQL Maps 相比,db4o 更加自然,无需过多 地引用第三方支持库。
开启数据库
db4o 怎样进行对象持久化呢?通过浏览目录可以发现,与传统的 RDBMS 一 样,db4o 也有自己的数据库文件, 在 db4o 中数据库文件的后缀名是“*.yap” 。让我们先来了解一下 db4o 对象数据库引擎的主要包结构:
com.db4o
com.db4o 包含了使用 db4o 时最经常用到的功能。两个最重要 的接口是 com.db4o.Db4o 和 com.db4o.ObjectContainer。com.db4o.Db4o 工厂 是运行 db4o 的起点,这个类中的静态方法可以开启数据库文件、启动服务器或 连接一个已经存在的服务器,还可以在开启数据库之前进行 db4o 环境配置。 com.db4o.ObjectContainer 接口很重要,开发过程中 99% 的时间都会用到它, ObjectContainer 可在单用户模式下作为数据库实例,也可作为 db4o 服务器的 客户端。每个 ObjectContainer 实例都有自己的事务。所有的操作都有事务保 证。当打开 ObjectContainer,就已经进入事务了,commit() 或 rollback() 时,下一个事务立即启动。每个 ObjectContainer 实例维护它自己所管理的已 存储和已实例化对象,在需要 ObjectContainer 的时候,它会一直保持开启状 态,一旦关闭,内存中数据库所引用的对象将被丢弃。
com.db4o.ext
你也许想知道为什么在 ObjectContainer 中只能看见很少 的方法,原因如下:db4o 接口提供了两个途径,分别在 com.db4o 和 com.db4o.ext 包中。这样做首先是为了让开发者能快速上手;其次为了让其他 产品能更容易的复制基本的 db4o 接口;开发者从这一点上也能看出 db4o 是相 当轻量级的。每个 com.db4o.ObjectContainer 对象也是 com.db4o.ext.ExtObjectContainer 对象。可以转换成 ExtObjectContainer 获 得更多高级特性。
com.db4o.config
com.db4o.config 包含了所有配置 db4o 所需的类。
com.db4o.query
com.db4o.query 包包含了构造“原生查询, NQ(Native Queries)”所需的 Predicate 类。NQ 是 db4o 最主要的查询接口。
db4o 提供两种运行模式,分别是本地模式和服务器模式。本地模式是指直接 在程序里打开 db4o 数据库文件进行操作:
ObjectContainer db = Db4o.openFile(“auto.yap”);
而服务器模式则是客户端通过 IP 地址、端口以及授权口令来访问服务器:
服务器端:
ObjectServer server=Db4o.openServer(“auto.yap”,1212);
server.grantAccess(“admin”,“123456”);
客户端:
ObjectContainer db=Db4o.openClient (“192.168.0.10”,1212,“admin”,“123456”);
两种方式都可以得到 ObjectContainer 实例,就目前 Java EE 应用环境来 看,服务器模式更有现实意义;而本地模式更适合于嵌入式应用。为了简化演示 ,本文在下面的例子都将采用本地模式。
在下面的例子里,我们都会用到下面两个对象: People 和 AutoInfo 对象 。
People 对象清单1:
清单1. People 对象
package bo;
public class People {
private java.lang.Integer _id;
private java.lang.String _name;
private java.lang.String _address;
private java.util.List _autoInfoList;
public java.lang.Integer getId() {
return _id;
}
public void setId(java.lang.Integer _id) {
this._id = _id;
}
public java.lang.String getName() {
return _name;
}
public void setName(java.lang.String _name) {
this._name = _name;
}
public java.lang.String getAddress() {
return _address;
}
public void setAddress(java.lang.String _address) {
this._address = _address;
}
public java.util.List getAutoInfoList() {
return this._autoInfoList;
}
public void addAutoInfo(AutoInfo _autoInfoList) {
if (null == this._autoInfoList)
this._autoInfoList = new java.util.ArrayList();
this._autoInfoList.add(_autoInfoList);
}
}
AutoInfo 对象清单2:
清单2. AutoInfo 对象
package bo;
public class AutoInfo{
private java.lang.Integer _id;
private java.lang.String _licensePlate;
private bo.People _ownerNo;
public java.lang.Integer getId () {
return _id;
}
public void setId (java.lang.Integer _id) {
this._id = _id;
}
public java.lang.String getLicensePlate () {
return _licensePlate;
}
public void setLicensePlate (java.lang.String _licensePlate) {
this._licensePlate = _licensePlate;
}
public bo.People getOwnerNo () {
return this._ownerNo;
}
public void setOwnerNo (bo.People _ownerNo) {
this._ownerNo = _ownerNo;
}
}
利用 set 方法把新对象存入 ObjectContainer,而对 ObjectContainer 中 已有对象进行 set 操作则是更新该对象。db4o 保存数据库很简单,下面就是一 个段完整的保存对象的代码:
AutoInfo 对象清单3:
清单3
package com;
import bo.AutoInfo;
import bo.People;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
public class DB4OTest{
public static void main(String[] args){
//打开数据库
ObjectContainer db = Db4o.openFile(“auto.yap”);
try{
//构造 People 对象
People peo = new People();
peo.setId(1);
peo.setAddress(“成都市”);
peo.setName(“张三”);
//构造 AutoInfo 对象
AutoInfo ai = new AutoInfo();
ai.setId(1);
ai.setLicensePlate(“川A00000”);
//设置 People 和 AutoInfo 的关系
ai.setOwnerNo(peo);
peo.addAutoInfo(ai);
//保存对象
db.set(peo);
}finally{
//关闭连接
db.close();
}
}
}
当我们运行上述代码,db4o 会自动创建“auto.yap”文件。让我们来看看到 底保存成功没有,打开 ObjectManager 工具,如图 1 所示。
图1. 对象数据库管理工具
“File”->“Open File”->选择刚才我们保存的“auto.yap”文件 (“auto.yap”文件可在项目的根目录下找到),最新的 ObjectManager 1.8 版本为我们提供了“Read Only”方式读取数据库文件,避免 ObjectManager 占 用数据库文件所导致的程序异常。
打开之后,如图 2 所示,刚才存贮的 People 对象已经在数据库中了,并且 还可以很直观的看到 AutoInfo 对象也放入了 ArrayList 中。这种可视化的对 象关系有利于我们对数据的理解,是传统 RDBMS 无法比拟的。有些开发者会说 ObjectManager 工具略显简单,这点我想随着 db4o 的不断发展会加入更多的特 性。在这个工具中,我们意外的发现了 Java 集合对象的踪影,db4o 把与 ArrayList 有直接关系的所有接口和父类都保存了,这样显得更直观,
在此,我保留了 _id 属性,这是因为通常在 Java EE 环境中,DAO 第一次 不是把整个对象都返回到表现层,而是只返回了“标题”、“发布时间”这些信 息(并隐式的返回id),接着 DAO 与数据库断开;要查看详情(比如文章内容 )就需要进行 findById 操作,这时 DAO 要再次与数据库交互,只有唯一标识 符才能正确地找到对象。这种懒加载方式也是很多书籍所推荐的。
回到本文的范例程序中,这个 _id 属性可由人工编码实现的“序列”进行赋 值,当然 db4o 也提供了内部标识符 Internal IDs,如图 2 中的 id=1669;以 及 UUIDs。
图2. 对象结构
查询数据库
和 RDBMS 一样,db4o 也有自己的查询语言,分别是 QBE(Query by Example)、NQ(Native Queries)、SODA(Simple Object Database Access) ,db4o 更推荐使用 NQ 进行查询。NQ 方式提供了非常强大的查询功能,支持原 生语言,也就意味着你可以使用 Java 来判断该对象是否符合条件,这是其他数 据库查询语言无法比拟的。在某些情况下, db4o 核心会将 NQ 翻译成 SODA 以 获得更高的性能。下面详细介绍一下这三种查询语言。
QBE(Query by Example)
QBE 规范可在这里下载。QBE 最初由 IBM 提出,同时业界也有许多和 QBE 兼容的接口,包括著名的 Paradox。有些系统,比如微软的 Access,它的基于 表单的查询也是受到了部分 QBE 思想的启发。在 db4o 中,用户可借用 QBE 快 速上手,可以很容易适应 db4o 存取数据的方式。
当利用 QBE 为 db4o 提供模板(example)对象时,db4o 将返回所有和非默 认值字段匹配的全部对象。内部是通过反射所有的字段和构造查询表达式(所有 非默认值字段结合”AND”表达式)来实现。
例如,利用 QBE 查找到车牌号为“川A00000”的车主姓名,这是一个级联查 询。清单4:
清单4
package com;
import java.util.List;
import bo.AutoInfo;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
public class DB4OTest{
public static void main(String[] args){
//打开数据库
ObjectContainer db = Db4o.openFile(“auto.yap”);
try{
//构造模板对象
AutoInfo ai = new AutoInfo();
ai.setLicensePlate(“川A00000”);
//查询对象
List list = db.get(ai);
for(int x = 0; x < list.size(); x++){
System.out.println(“车主姓名:”+list.get(x).getOwnerNo ().getName());
}
}finally{
//关闭连接
db.close();
}
}
}
但是 QBE 也有明显的限制:db4o 必须反射模板(example)对象的所有成员 ;无法执行更进一步的查询表达式(例如 AND、OR、NOT 等等);不能约束 0( 整型)、””(空字符串)或者 null(对象),因为这些都被认为是不受约束 的。要绕过这些限制,db4o 提供了 NQ(Native Queries)。
SODA(Simple Object Database Access)
SODA ,简单对象数据库访问,请查看官方站点,其中一位主要维护者是 Carl Rosenberger,Carl 正是 db4o 首席架构师。
SODA 就是一种与数据库通讯的对象 API。最终的目标是实现类型安全、对象 复用、最小的字符串使用、与编程语言无关等特性。SODA 是 db4o 最底层的查 询 API,目前 SODA 中使用字符串来定义字段,这样将不能实现类型安全也无法 在编译时检查代码,而且写起来较麻烦,当然要达到设计目标这个阶段是必须的 。大部分情况下 NQ(Native Queries)是很好的查询接口,不过遇到动态生成 查询的时候 SODA 就大有作为了。
通过 SODA 查找到车牌号为“川A00000”的车主姓名。清单5:
清单5
package com;
import java.util.List;
import bo.AutoInfo;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.query.Query;
public class DB4OTest{
public static void main(String[] args){
//打开数据库
ObjectContainer db = Db4o.openFile(“auto.yap”);
try{
//构造查询对象
Query query=db.query();
//设置被约束实例
query.constrain(AutoInfo.class);
//设置被约束实例的字段和约束条件
query.descend(“_licensePlate”).constrain(“川A00000”);
//查询对象
List list = query.execute();
for(int x = 0; x < list.size(); x++){
System.out.println(“车主姓名:”+list.get(x).getOwnerNo ().getName());
}
}finally{
//关闭连接
db.close();
}
}
}
通过 API,发现 Query 实例增加了 sortBy 按字段排序方法和 orderAscending正序、orderDescending 倒序排列方法,SODA 比 QBE 更进了一 步。
NQ(Native Queries)
精彩总是在最后出场,NQ 才是 db4o 查询方式中最精彩的地方!有没有想过 用你熟悉的的编程语言进行数据库查询呢?要是这样,你的查询代码将是 100% 的类型安全、100% 的编译时检查以及 100% 的可重构,很奇妙吧?NQ 可以做到 这些。
有两篇论文专门讲解了 NQ 的基本概念和设计思路,分别是 《Cook/Rosenberger,持久对象原生数据库查询语言》 和 《Cook/Rai,Safe Query Objects: Statically Typed Objects as Remotely Executable Queries 》。作为结果集的一部分,NQ 表达式必须返回 true 值来标记特定实例。如果 可能的话 db4o 将尝试优化 NQ 表达式,并依赖索引来运行表达式。
通过 NQ 查找到车牌号为“川A00000”的车主姓名。清单6:
清单6
package com;
import java.util.List;
import bo.AutoInfo;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.query.Predicate;
public class DB4OTest{
public static void main(String[] args){
//打开数据库
ObjectContainer db = Db4o.openFile(“auto.yap”);
try{
List list = db.query(new Predicate() {
public boolean match(AutoInfo ai) {
//这样才是类型安全的
return ai.getLicensePlate().equals(“川 A00000”);
}
});
for(int x = 0; x < list.size(); x++){
System.out.println(list.get(x).getOwnerNo().getName ());
}
}finally{
//关闭连接
db.close();
}
}
}
必须指出 NQ 的一个的问题是:在内部,db4o 设法把 NQ 转换成 SODA。但 并不是所有的查询表达式都可以成功转换。有些查询表达式的流向图 (flowgraph)非常难于分析。这种情况下,db4o 将不得不实例化一些持久对象 来真实地运行 NQ 表达式。
正在开发中的 NQ 查询优化器就可以化解这个障碍,它将分析 NQ 表达式的 每个部分,以确保最少量的实例化对象,以此提高性能。当然,优化器的不是灵 丹妙药,关键还需要自己多优化代码。
开发 Java EE 项目经常会用到分页,怎样用 NQ 实现呢?向数据库写入六条 记录。清单7:
清单7
package com;
import java.util.List;
import bo.AutoInfo;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.query.Predicate;
public class DB4OTest{
public static void main(String[] args){
//打开数据库
ObjectContainer db = Db4o.openFile(“auto.yap”);
try{
List list = db.query(new Predicate() {
public boolean match(AutoInfo ai) {
return true;
}
});
//记录总数
Integer count = list.size();
//每页两条,分三页
for(int x = 0; x < 3; x++){
System.out.println(“第”+x+“页:”+list.get (x*2).getLicensePlate());
System.out.println(“第”+x+“页:”+list.get (x*2+1).getLicensePlate());
}
}finally{
//关闭连接
db.close();
}
}
}
我们发现,在进行 NQ 查询时并没有加入任何条件(无条件返回 true),是 不是相当于遍历了整个数据库?db4o 的设计者早就想到了这个问题,当 db.query() 执行完毕返回 list 实例的时候,db4o 只是与数据库同步取出内部 IDs 而已,并没有把所有的 AutoInfo 对象全部取出,只有在 list.get (x*2).getLicensePlate() 之后才会去根据 IDs 取出记录。所以不必担心性能 问题。
结论
Db4o 篇3
Android开发者应该都知道, Android平台是以SQLite引擎作为系统的数据库引擎。SQLite是一款应用颇广的轻量级关系型数据库 (RDB) 引擎, 支持多数SQL92标准。而本文中提到的Db4o数据库却是一款嵌入式对象数据库 (Object database) 。
作为对象数据库, Db4o以对象作为处理单位 (关系型数据库的是记录) , 其所有的操作接口, 例如:添加、更新、删除和查询等, 都是以对象为单位。有关Db4o数据库的详细说明, 读者可以访问Db4o的官方网站http://www.db4o.com/来获取更多的参考信息。
2 设计过程
2.1 Db4o开发包
Db4o开发包分为Java和.NET两个版本, 分别支持在Java和.NET平台上的开发。对于Android平台而言, 只可能接收Java版本的SDK, 但这并不表示Android平台可以“接纳”任何的Java开发包。Android虚拟机Dalvik所支持的字节码格式是Dex, 与普通的Java虚拟机所支持的字节码格式不同。如果强制将普通Java包加入到Android工程, Android打包工具就会抛出“无法转换到Dalvik格式”的错误, 如下所示:
当读者从Db4o官方网站 (http://www.db4o.com/Download Now.aspx) 下载到最新的Db4o Java版本的开发包, 解压之后会发现, Java版本的开发包又按照JDK版本存在3个子版本:1.1、1.2和5。如图1所示。
通过测试, Android平台所支持的Java子版本是JDK5, 即文件名形为“db4o-xxx-java5”的包文件。
2.2 Db4o开发包主要功能
Db4o数据库可以实现对内存中的对象进行存储, 对Db4o数据库中存储的对象进行查询和删除。通过Db4o开发包可以实现对Db4o数据库的管理、添加对象、删除对象和对象查询。对于对象存储功能, 或许可以通过简单的序列化 (Serialize) 来将对象保存到存储设备中;但是对于对象查询功能, 可就不能这么简单了, 特别是当对象数量较多的情况下。Db4o数据库提供了多种对象查询方式, 有兴趣的读者可以参考Db4o的相关资料。
2.2.1 数据库管理
不同于Oracle等大型数据库, Db4o数据库的数据存储比较简单, 一个数据库文件对应一个数据库 (有点类似与DBF数据库引擎) 。所谓对Db4o数据库的管理, 就是对Db4o数据库文件的管理。
和文件管理一样, 对Db4o数据库的管理包括创建、删除、移动、复制等。但是在Android平台, 对于外部存储器 (SD卡) 的写入需要在工程清单文件 (Android Manifest.xml) 中声明允许写入外部存储器的使用许可 (Uses-permission) , 如以下代码所示:
使用Db4o类的静态方法“open File”就可以打开指定的Db4o数据库, 并返回一个对象容器接口 (Object Container) , 为后续对对象的操作提供容器。
使用Db4o类实例的“close”就可以关闭当前的数据库。
2.2.2 新增对象
对于日记账簿工具而言, 所要新增的内容是支出事项, 也就是说每一条支出事项对应一个对象, 所以必须定义一个代表支出事项的对象类。有了支出对象, 就可以通过Object Container接口的“store”方法来存储事项信息。
与一般对象定义不同的是, 在Android平台, 对象如果需要在Activity中传递 (例如:查询Activity需要将对象集合传递给列表Activity进行内容显示) , 则该对象类必须实现Parcelable接口。
Parcelable接口是Android所定义的核心机制, 在Activity之间所传递的数据都经过“打包”的。Parcelable接口提供了一组写入内容到包和从包中读取数据的方法。
2.2.3 删除对象
使用Object Container接口的“delete”方法就可以删除指定对象。
2.2.4 查询对象
使用Object Container接口的“query”方法 (原生查询) 和“query By Example”方法 (按例查询) 就可以用于查询指定条件的对象条目, 并返回对象集接口 (Object Set) 。
除了原生查询和按例查询, Db4o还提供了一种SODA的查询方式, 有兴趣的读者可以参考Db4o数据库的有关技术资料。
Object Set继承于List接口, 所以一旦获取到对象集接口, 就可以方便地对其中的对象条目进行处理, 例如:显示、汇总、分类等。
2.3 界面设计
2.3.1 主界面
图2是该日记账簿工具运行的主界面, 操作系统是Android 2.3.6, 屏幕分辨率为480×800像素。
代码1是图2所示的主界面的布局定义, 其中只包含一张背景图片。
代码2是主界面选项菜单资源的定义, 其中包含:添加、浏览和查询3个菜单项。
2.3.2 记录添加
当用户选择主选项菜单中的“添加记录”项后将会切换到记录添加界面, 记录添加完毕之后, 记录添加界面将关闭, 并提示记录存储是否成功。如图3所示。
代码3是记录添加界面的布局定义, 其用到线性布局和表格布局。
2.3.3 记录浏览
当用户选择主选项菜单中的“浏览记录”项后将会切换到记录浏览界面, 并可以通过按钮“后一条”和“前一条”来顺序浏览所有的记录, 如图4所示。
可以从图4中看出, 若当前记录之后有记录, 按钮“后一条”才可用;若当前记录之前有记录, 按钮“前一条”才可用。
记录浏览界面的布局结构和记录添加界面基本一致, 在此不再重复。
2.3.4 记录查询
当用户选择主选项菜单中的“查询记录”项后将会切换到记录查询界面, 如图5中左图所示。
记录查询支持模糊匹配, 当用户选择图5中的按钮“查询”后, 将会获取备注 (Comments) 属性值中包含“超市”文字的所有对象记录。
记录查询界面的布局结构和记录添加界面基本一致, 在此不再重复。
2.3.5 记录列表
当用户选择记录查询界面中的按钮“查询”后将会切换到记录列表界面。当用户选择列表中某一项时, 会在页脚视图中会显示所选项的内容, 如图5中右图所示。
(1) 记录列表界面布局
代码4是记录列表界面布局的定义, 其主要组件是列表视图。
(2) 列表行视图布局
代码5是记录列表界面中行视图的布局定义, 其采用表格布局。
2.4 功能模块
根据功能之间的耦合度, 作者将该日记账薄分为Activity和后台功能两块。
2.4.1 Activity组件
(1) 主Activity (Journal Book Act) , 提供用户与选项菜单的交互, 是其他Activity的调用者。
(2) 记录添加Activity (Append Rec Act) , 提供用户与记录添加界面的交互。
(3) 记录浏览Activity (Review Rec Act) , 提供用户与记录浏览界面的交互。
(4) 记录查询Activity (Lookup Rec Act) , 提供用户与记录查询界面的交互, 是记录列表Activity的调用者。
(5) 记录列表Activity (Report Rec Act) , 用于显示查询所得到的记录集信息。
图6是该日记账簿工具中Activity的交互示意图。
2.4.2 公共定义
(1) 支出对象类 (Payout) , 用于代表支出事项, 具有时间戳、备注和金额等属性。
(2) 支出对象查询谓词 (Payout Predicate) , 用于具体实现支出对象的查询规则。
(3) 对象数据库工具类 (Odb Util) , Db4o数据库API的封装API。
(4) 系统工具类 (Foo Sys Util) , 提供一些系统功能, 例如:获取当前日期时间、日志输出等。
2.5 工程清单
代码6是该日记账簿工程的清单文件 (Android Manifest xml) 的内容:
代码6中, 读者可以看出, 除了主Activity之外, 还有4个Activity。
第7行声明了允许写外部存储器 (SD卡) 的使用许可, 这样才能保证程序正常地在SD卡中创建Db4o数据库。
3 开发过程
3.1 部署Db4o开发包
从Db4o官方网站 (http://www.db4o.com/Download Now aspx) 下载最新Java版本的Db4o开发包压缩文件。在解压之后的lib文件夹中, 可以找到JDK5版本的Jar文件。
在Eclipse IDE中以“添加外部Jar包”的方式将该Jar文件添加到当前工程中, 或者直接改写工程文件夹中的类路径设置文件 (.classpath) , 如代码7所示。
代码7中第6行, 即为添加Db4o Jar文件为工程的包文件。实际上, 使用IDE添加Jar文件最终也会添加类路径设置, 但Jar文件的路径使用的是绝对路径, 不便于工程的迁移。
3.2 功能实现
3.2.1 支出对象定义
代码8是支出对象的完整定义, 该对象类实例就是Db4o数据库所要存储的条目:
代码8中, 支出对象实现了Parcelable接口, 其中必须要定义一个名为“CREATOR”的全局静态成员, 该成员的“create From Parcel”方法定义了从包中生成对象的方法“Payout (in) ”。
第24行中的“write To Parcel”方法定义了将对象写入到包中的过程。至此, 读者可以明白, 通过Parcelable接口的框架, 外部调用组件可以将对象集写入到包中, 也可以从包中读出对象集。
3.2.2 数据库管理
代码9是Db4o数据库管理的关键代码, 包括打开和初始化数据库文件。
代码9中, 必须使用指定的配置来打开数据库, 并为其设置特定的类反射器 (Reflector) , 否则在打开已经存在的数据库时, Db4o平台会抛出类反射器有关的异常。
3.2.3 添加记录
代码10是在记录添加Activity中提交记录添加的关键代码:
代码10中, 记录添加Activity首先对提交的内容进行检查, 然后根据提交的内容生成一个新的支付对象, 然后通过调用对象数据库工具类的添加方法将该对象进行存储, 其运行效果如图3所示。
代码11是对象数据库工具类中添加记录对象的方法:
3.2.4 浏览记录
代码12是记录浏览Activity初始化时从Db4o数据库中获取对象集的主要代码:
代码12中第5行, 记录浏览Activity调用了对象数据库工具类的方法来获取数据库中所有对象。获取完毕之后, 将记录对象的属性值与显示组件进行绑定。
代码13是对象数据库工具类中获取所有对象的方法:
3.2.5 查询记录
代码14是记录查询Activity执行查询行为的主要代码:
代码14中, 记录查询Activity根据用户的选择来生成支出对象的谓词 (Predicate) 对象, 然后以谓词对象为参数, 调用对象数据库工具类的查询方法来获取对象集。
记录查询Activity启动记录列表Activity, 并将查询获取到的对象集传递给该Activity。
代码15是对象数据库工具类中查询记录对象的方法。
3.2.6 对象集传递
代码16是在记录列表Activity中获取有记录查询Activity所传来的对象集的主要代码:
读者可以看出, 代码16中的过程和代码14中的传递对象集的过程是逆向的。代码14中是将对象集放入包中并通过意向对象 (Intent) 传递, 而代码16中是从意向对象中获取数据包, 并从中提取对象集。
3.2.7 查询谓词
代码17是查询支付对象的谓词 (Predicate) 类的定义, 该类定义了支付对象的匹配规则, Db4o数据库引擎以该规则进行对象集的过滤:
代码17中, 自定义谓词类必须继承于Db4o的谓词类 (Predicate) , 通过重载谓词类的匹配接口 (match) 来定制支付类对象的匹配规则。
4 结语
通过一个日记账簿工具阐述了在Android平台进行Db4o数据库应用方面的开发过程。不仅让读者了解外部开发包引入到Android平台的方法和要点, 而且还领会到对象数据库Db4o的主要功能以及在Android平台中的使用要点。
以下是应该注意的要点:
(1) 并不是所有Java开发包都能够纳入Android平台, 至少能够支持Dex字节码格式。
(2) 在Eclipse IDE中通过菜单添加外部Jar包, 引用的是该Jar文件的绝对路径, 而直接编辑工程的类路径配置文件可以引用Jar文件的相对路径, 更利于工程文件夹的迁移。
(3) 在Android平台, 在SD卡中创建Db4o数据库需要在工程清单文件中声明允许写外部存储器的使用许可。
(4) 为了保证正常打开已经存在的Db4o数据库, 在打开数据库文件时, 必须指定配置, 并为配置指定特定的类反射器。
(5) 为了满足对象能够在Activity组件之间进行传递, 对象类必须实现Parcelable接口。
摘要:介绍了将对象数据库Db4o的开发包 (SDK) 移植到Android平台, 并以Db4o数据库为引擎, 开发一款日记账簿工具的实践过程。通过此开发案例, 读者不仅可以了解Android平台移植的模式和要点, 而且还可以了解在Android平台中开发Db4o数据库程序的过程和特点。
相关文章:
托妮莫里森02-19
常用设备安全操作规程02-19
安全教案-03常用灭火器使用方法02-19
商会中秋联谊会致辞02-19
电子商务常用安全技术02-19
浅析油罐常用安全附件的维护与保养02-19
常用安全名词解释02-19
常用钢厂安全知识和02-19
电力企业常用安全用语02-19