成都心情

  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理 ::
  98 随笔 :: 2 文章 :: 501 评论 :: 1 Trackbacks

前言

在开源面向对象数据库 db4o 之旅 系列文章的第 1 部分:初识 db4o 中,作者介绍了 db4o 的历史和现状,应用领域,以及和 ORM 等的比较; 在第 2 部分:db4o 查询方式中, 作者介绍了 db4o 的三种不同的查询方式:QBE、SODA 以及 Native Queries,并分别通过这三种不同的途径实现了两个关联对象的查询。

前面我们已经介绍了如何在 db4o 中查询以及添加对象,在本文中我们将会向您介绍在 db4o 中如何对对象进行更新以及删除操作。
 

更新数据

场景一

我们来设想这样的场景:一位名叫“张三”的人买了车,并上好了牌照(如本系列第二部分之代码),而他基本信息的地址并不详细,只写了“成都市”,在一次主管部门检查此人信息的时候,发现了这个问题,并立即着手修改。

在 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. 修改地址

db4o31.jpg

与本系列文章第二部分不同的是,我们利用 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. 修改地址和车牌(不成功)

db4o32.jpg

其实这也是 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. 修改地址和车牌(成功)

db4o33.jpg

删除数据

场景三

“张三”换了工作后,事业发展很快,准备把车卖了换新的,于是他去交管部门办理移交手续,删除关联的车辆信息清单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. 删除车辆信息

db4o34.jpg

场景四

在场景三的基础上修改一下,设想“张三”由于工作不顺,导致最后维护汽车的开支都困难,他不得不退出有车一族的行列清单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 和他联系。


张黄瞩,热爱开源软件,熟悉 Java/C/C++ 编程语言,对数据库技术网络技术均感兴趣。你可以通过 zhanghuangzhu@gmail.com 联系他。


IBM DeveloperWorks(IBM DW) 版权所有!引用、转贴本文应注明本文来自 IBM DW。
posted on 2006-12-30 19:11 Rosen 阅读(5829) 评论(17)  编辑  收藏 所属分类: Versant db4o 中文项目

评论

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-02-14 15:30 lqixv
我想问一下,是不是这个数据库不适合用来开发web ?因为我以前用过asp,很喜欢asp + access的模式来开发小型应用。所以现在想找一个用在 java 方面的数据库。原来想用 Derby,后来发现 Derby 比 db4o 性能上差很多,因此又想用 db4o。但又看到一些文章,好像说 db4o 不适合用于 web 开发,因为其不能使用数据库连接池,不知是不是,请指教,谢谢。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-02-18 18:39 Rosen
@lqixv
对于连接池我已经提交给db4o团队讨论过了,不过他们不赞成使用连接池方式,觉得这完全没有必要,以后的db4o会分成3个版本针对不同领域,相信随着C/S性能的提高,db4o可以应用在WEB APP中。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-02-27 12:14 lqixv
想知道,现在的 db4o 能不能代替 access 进行 web 开发?  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-02-27 19:19 Rosen
@lqixv
这个倒是完全可以的。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-03-05 14:18 Sha Jiang
> 对于连接池我已经提交给db4o团队讨论过了,不过他们不赞成使用连接池方
> 式,觉得这完全没有必要
为什么没有必要呢?

对于Java/JDBC,“连接”一般是指javax.sql.Connection对象,
那么对于db4o而言,它的“连接”对象可能是指什么呢?
如果不存在着这么一种“对象”,或db4o在建立连接时,可能并不需做创建对象这样“昂贵”的工作。那么可能实现连接池就是“没有必要”的。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-03-05 15:01 Rosen
@Sha Jiang
这个连接是 OC 对象实例,利用 apache common 提供的 pool 产品,或 java 自带的线程安全队列进行包装。
正如你说到的,以前 C/S 模式下建立连接是昂贵的,所以提出了这种概念,但是随着性能提高,这种概念是没有必要的了。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-08-01 02:23 张三
Db4o是否支持类似Mysql的limit语句。

由于Access不支持linmit语句,分页操作占用资源极其昂贵,并且

Access的分页操作非常不方便,效率很低。

我想知道Db4o是否能够像limit一样非常方便支持分页。

如果能够直接支持,我想我会使用这个数据库的:)

======================================
我抛弃Access数据库的最直接原因就是:

1:Access没有查询分析器

2:Access不支持Limit分页

3:Access效率低下

4:Access自动递增ID在建立之后无法更改

不知道Db4o是否能很好的支持以上功能。。。特别是分页功能。

谢谢盼回复。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-08-01 10:02 Rosen
@张三
呵呵,你用了文章中的别名。
你的问题很具体,目前我换了工作,平时很忙,都很久没具体关注过了,就我的经验是有查询分析器的,但是功能还比较弱;limit也不支持,不过可以在查询的时候进行限制;对于id,内部有一个自己的id,但是不能进行人为干预,我的思路是在对象中自己定义id字段,人工维护。
你可以到官方中文论坛上发帖子,也可以在上面找到官方QQ群,和开发者一起讨论。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-08-03 18:10 张三
官方论坛上一片冷清,不管在中文还是英文的版面。

哎,其实我在前一个月也想用做一个内嵌数据库系统。

但国内喜欢开源的人太少了。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-08-04 15:52 Rosen
@张三
喔,官方论坛也是这样,分析原因,我认为主要还是db4o对企业级应用支持不够。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-08-27 15:16 张三
最主要的查询方式只有一种,我们另外提供了49种查询方式。

先介绍第一种查询方式:............

...................

.................

..................

现在,第49种查询方式讲完了,我们要开始讲最激动人心的第50种查询方式了

...(第50种3句话讲完)

其实最后一种查询方式很简单,只要1行代码就可以完成了。

我们推荐您使用最后一种查询方式。

---------------------------------------
IBM的什么垃圾数据库,我研究了近一个月了,没有什么进展!!
不管是Access,Mysql,MsSql,随便哪个,一个月都没有像这样的:一无所获!

===================1==================================
三种查询方式,分别4种语言极其复杂!(根本不像教程说的那样简单)
4种语言分别为:Java1.5 Java1.4 Net1.1 Net2.0
虽然语法差不多,但查询语句完全不一样!!!!

也就是说 一个简单的查询 会存在3 * 4=12种方法。并且这12种方法在文档里杂乱不堪得堆在一起。
说是推荐NQ查询方式,但其他两种查询方式出现的频率是NQ的几倍!而NQ却没看到怎么描述!
所以,db4o开发组,文档编写者根本不知道db4o重点在哪里!
=====================2============================
ObjectManager 这绝对是个垃圾软件
1首先,要运行这个软件,必须安装JVM 1.5。并且运行起来速度慢得惊人!(这个问题,我研究了近4小时)
2研究了一下午发现,只能看到类结构,数据根本不能查看。
3除了更改索引,就只能更改类名。其他操作没有!
更改类名根本就是鸡肋!一但更改了类名,与程序中的类不匹配会怎么样?我没试过!
4建议将此软件改为ObjectView, Manager这个词对这个软件来说不合适。
并且,这样的查看功能在Visual Studio 2005中,非常简单,并且功能比此ObjectView来说要强得多。
5所以,建议将该鸡肋工程放弃的好!这个软件根本就是一个垃圾。
==========================3=================================
没有能看的开发文档,我指的是中文!
有,也是简单几篇,并且只有几页纸!
其他的网上都是盗来盗去的连接,开发之旅123
这个数据库怎么用都不知道,连个文档都没有!!真是垃圾!
========================4============================
与其说:无管理 还不如说:无法管理!
根本没有管理工具,对于使用者来说这个数据库是不可见的。
对于开发者来说,这个数据库同样是不可见的!
如果不小心多存了一个数据进去,现在唯一的办法就是:写一个删除这个数据的程序!
换个角度,简单的说:Access如果不小心写了个数据进去,可以很方便的将这个数据删除!鼠标点两下就可以完成的事,在db4o中竟然这么麻烦。

在程序开发后期,或者要清理数据库时,不得不另外开发个程序来查看数据库的数据,并进行删除。
这在其他数据库中弹指即可完成的事,在db4o中,竟然这么麻烦!极其麻烦!
========================5=====================
在网上找并发查询的相关资料,竟然一无所获!竟然没人知道多线程下
如何进行并发操作的。
唯一的收获就是:有人说在写数据时,锁定整个连接!!!!!
垃圾的办法,我自己写个数据库引擎都比这强!!!
=======================6======================
一般写dbms时,会将 数据结构 和数据库中的字段进行映射,一对一关系。就在这点上,有点麻烦。
而,如果用反射机制+接口 直接生成数据库表,先期投资较大,以后也比较方便的。
db4o也只是在这方面比较占优势,在其他方面,没有什么大的优势。
如果要说到内嵌,那Mysql占优势,有源代码,修改一下嵌到程序里也不是什么难事。或者启动程序时,启动mysql,关闭程序时关闭mysql.
======================7====================================
总结:db4o 性能一般,先期投资不大,后期会被它搞死!
其数据库不管对谁,都是一无所知的。
没有好的文档支持,即便有也是12种方法的、杂乱不堪的(并且非常罗嗦,主次不分)。
没有可视化的程序支持,管理维护此数据库代价将会非常昂贵!
(必须自己写一个类似管理器的东西,代价一定很大,与其这样,我还不如写一个反射+自动生成表的程序)

如果一但上了此船,想要转向其他的数据库,转换也是非常昂贵的。
(Access -> Mssql 是很简单的,可以导入+修改,其他数据库雷同)
如果要转换,必须写代码。。。。。不得不晕!

对于这样的数据库,我不知道Intel使用它是否是被迫的!

就写到这里,对这个数据库很不爽!   回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-08-27 22:16 Rosen
不知道张三同志从哪里摘抄下来的文字?可否给个链接?thx
另外,我想说的是:rdbms已经发展了几十年,从理论到应用已相当成熟,请给oodb一个发展的机会,埋怨是没用的,为何不投入进来贡献自己的力量?  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-08-28 19:55 张三
抱歉的是,这是我写的骂帖。。。。

一个数据库出来,首先必须有实用性,db4o在实用性上很差,后期管理费用非常昂贵。

也就是说必须:可用。

而db4o连基本的要求都达不到,还拿到网上到处吹嘘。

不知道Intel是怎么想到用这个数据库的。。。。。

前段时间刚看到版本6.1,上次去网上看,已经6。3了。。。

版本更新何其快,但我没有看到任何的数据库更新程序,我没有看到如何将6.1数据库更新到6.3的,官方也没有说:不需要更新 这样的话。

如果我是6.1的用户,我没有办法更新到6.3我会很郁闷,因为他没有一个可视化的界面,甚至同过手动都无法更新到6.3.

就是这样,所以我放弃了,我选择了Mysql。。。。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-08-29 00:27 Rosen
@张三
我能理解你的心情,我们都在期待它的完善并不断与他人分享自己的体验,哪怕是像你这样的痛苦体验。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-09-09 23:27 张三
我准备写一个ORM层,用法基本和db4o差不多,也是用反射原理。

但性能应该比db4o要好些,也好管理。。。


嘿嘿,db4o给我的启发挺大的。  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2007-09-10 22:29 Rosen
@张三
good news  回复  更多评论
  

# re: 开源面向对象数据库 db4o 之旅: 深入 db4o “db4o 之旅(三)” 2008-07-02 06:34 张三
ORM 1.0版已经完成了.呵呵,映射效果不错.

准备开发Sqlite的ORM映射方法.  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: