DBMNG数据库管理与应用

书籍是全世界的营养品。生活里没有书籍,就好像没有阳光;智慧里没有书籍,就好像鸟儿没有翅膀。
当前位置:首页 > 数据库基础 > DB4O

开源面向对象数据库db4o深入学习和测试

前言

在开源面向对象数据库 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. 修改地址
图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. 修改地址和车牌(不成功)
图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. 修改地址和车牌(成功)
图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. 删除车辆信息
图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 我们会发现数据库已经清空了,张三的购车经历到此结束。

from:http://blog.csdn.net/sunny_sailor/article/details/8562929

本站文章内容,部分来自于互联网,若侵犯了您的权益,请致邮件chuanghui423#sohu.com(请将#换为@)联系,我们会尽快核实后删除。
Copyright © 2006-2023 DBMNG.COM All Rights Reserved. Powered by DEVSOARTECH            豫ICP备11002312号-2

豫公网安备 41010502002439号